1 /*---------------------------------------------------------------------------* 2 Project: NintendoWare 3 File: gfx_ParticleCollection.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_PARTICLECOLLECTION_H_ 17 #define NW_GFX_PARTICLECOLLECTION_H_ 18 19 #include <nw/gfx/gfx_GfxObject.h> 20 #include <nw/gfx/gfx_ParticleSet.h> 21 #include <nw/gfx/gfx_ParticleShape.h> 22 23 #include <nw/gfx/res/gfx_ResParticleCollection.h> 24 25 #include <nw/os.h> 26 27 namespace nw 28 { 29 namespace gfx 30 { 31 32 namespace internal 33 { 34 //! パーティクルで用いるショートベクタ演算の最大の処理単位です。 35 const int PARTICLE_SIMD_WIDTH_MAX = 8; 36 } // namespace internal 37 38 class ParticleSet; 39 class ParticleCollection; 40 41 //--------------------------------------------------------------------------- 42 //! @brief パーティクルの粒子の情報を表すクラスです。 43 //--------------------------------------------------------------------------- 44 class ParticleCollection : public GfxObject 45 { 46 private: 47 NW_DISALLOW_COPY_AND_ASSIGN(ParticleCollection); 48 49 public: 50 NW_UT_RUNTIME_TYPEINFO; 51 52 //! @brief パーティクルのための属性情報です。 53 //! @details :private 54 struct ParticleAttribute 55 { 56 s32 m_Usage; 57 bool m_IsStream; 58 f32* m_Stream; 59 }; 60 61 //---------------------------------------- 62 //! @name 作成/破棄 63 //@{ 64 65 //! @brief リソースからParticleCollectionノードを生成します。 66 //! 67 //! @param[in] parent 親のノードです。 68 //! @param[in] resource リソースです。 69 //! @param[in] mainAllocator メインアロケータです。 70 //! @param[in] deviceAllocator デバイスアロケータです。 71 //! @param[in] shape シェイプです。 72 //! 73 //! @return 生成されたParticleCollectionノードです。 74 //! 75 static ParticleCollection* Create( 76 ParticleSet* parent, 77 ResParticleCollection resource, 78 os::IAllocator* mainAllocator, 79 os::IAllocator* deviceAllocator, 80 ParticleShape* shape); 81 82 //! @brief 生成時に必要なメモリサイズを取得します。 83 //! @param[in] resource リソースです。 84 //! @param[in] alignment 計算に用いるアライメントです。2 のべき乗である必要があります。 85 //! @return 必要なメモリサイズです。 86 static size_t GetMemorySize( 87 ResParticleCollection resource, 88 size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) 89 { 90 os::MemorySizeCalculator size(alignment); 91 92 GetMemorySizeInternal(&size, resource); 93 94 return size.GetSizeWithPadding(alignment); 95 } 96 97 //! @details :private 98 static void GetMemorySizeInternal( 99 os::MemorySizeCalculator* pSize, 100 ResParticleCollection resource); 101 102 //! @brief 生成時に必要なデバイスメモリサイズを取得します。 103 //! @param[in] resource リソースです。 104 //! @param[in] alignment 計算に用いるアライメントです。2 のべき乗である必要があります。 105 //! @return 必要なデバイスメモリサイズです。 106 static size_t GetDeviceMemorySize( 107 ResParticleCollection resource, 108 size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) 109 { 110 os::MemorySizeCalculator size(alignment); 111 112 GetDeviceMemorySizeInternal(&size, resource); 113 114 return size.GetSizeWithPadding(alignment); 115 } 116 117 //! @details :private 118 static void GetDeviceMemorySizeInternal( 119 os::MemorySizeCalculator* pSize, 120 ResParticleCollection resource); 121 122 //@} 123 124 //---------------------------------------- 125 //! @name 取得/設定 126 //@{ 127 128 //! @brief リソースを取得します。 129 //! @return リソースを返します。 GetResParticleCollection()130 ResParticleCollection GetResParticleCollection() 131 { 132 return this->m_ResParticleCollection; 133 } 134 135 //! @brief リソースを取得します。 136 //! @return リソースを返します。 GetResParticleCollection()137 const ResParticleCollection GetResParticleCollection() const 138 { 139 return this->m_ResParticleCollection; 140 } 141 142 //! @brief パーティクル数の上限を取得します。 143 //! @return パーティクル数の上限を返します。 GetCapacity()144 int GetCapacity() const 145 { 146 return this->m_Capacity; 147 } 148 149 //! @brief パーティクル数を取得します。 150 //! @return 現在のパーティクル数を返します。 GetCount()151 int GetCount() const 152 { 153 return this->m_Count; 154 } 155 156 //! @brief パーティクル数を設定します。 157 //! @return 現在のパーティクル数を設定します。 158 //! @details :private SetCount(int count)159 void SetCount(int count) 160 { 161 this->m_Count = count; 162 } 163 164 //! @brief 有効なパーティクルのインデックスの最小値を取得します。 165 //! @details :private GetMinActiveIndex()166 u16 GetMinActiveIndex() const 167 { 168 return this->m_MinActiveIndex; 169 } 170 171 //! @brief 有効なパーティクルのインデックスの最大値を取得します。 172 //! @details :private GetMaxActiveIndex()173 u16 GetMaxActiveIndex() const 174 { 175 return this->m_MaxActiveIndex; 176 } 177 178 //! @brief 有効なパーティクルのインデックスの最小値を設定します。 179 //! @details :private SetMinActiveIndex(u16 minActiveIndex)180 void SetMinActiveIndex(u16 minActiveIndex) 181 { 182 this->m_MinActiveIndex = minActiveIndex; 183 } 184 185 //! @brief 有効なパーティクルのインデックスの最大値を設定します。 186 //! @details :private SetMaxActiveIndex(u16 maxActiveIndex)187 void SetMaxActiveIndex(u16 maxActiveIndex) 188 { 189 this->m_MaxActiveIndex = maxActiveIndex; 190 } 191 192 //! @brief 指定された属性がストリームかどうかを調べます。 193 //! @param[in] usage 利用種別です。 194 //! @return ストリームの場合はtrueを返します。 IsStream(ParticleUsage usage)195 bool IsStream(ParticleUsage usage) const 196 { 197 NW_ASSERT(usage >= 0 && usage < PARTICLEUSAGE_COUNT); 198 199 return this->m_IsStream[usage]; 200 } 201 202 //! @details :private GetBufferSide()203 bool GetBufferSide() const 204 { 205 return this->m_BufferSide; 206 } 207 208 //! @brief 指定された属性のストリームのポインタを取得します。 209 //! @param[in] usage 利用種別です。 210 //! @param[in] side バッファの使用目的です。 211 //! @return ストリームを返します。 GetStreamPtr(ParticleUsage usage,ParticleBuffer side)212 void* GetStreamPtr(ParticleUsage usage, ParticleBuffer side) 213 { 214 NW_ASSERT(usage >= 0 && usage < PARTICLEUSAGE_COUNT); 215 216 if (!this->m_IsStream[usage]) 217 { 218 return NULL; 219 } 220 221 if (this->m_BufferSide) 222 { 223 side = (ParticleBuffer)(1 - side); 224 } 225 226 return this->m_StreamPtr[usage][side]; 227 } 228 229 //! @brief 指定された属性のストリームのポインタを取得します。 230 //! @param[in] usage 利用種別です。 231 //! @param[in] side バッファの使用目的です。 232 //! @return ストリームを返します。 GetStreamPtr(ParticleUsage usage,ParticleBuffer side)233 const void* GetStreamPtr(ParticleUsage usage, ParticleBuffer side) const 234 { 235 NW_ASSERT(usage >= 0 && usage < PARTICLEUSAGE_COUNT); 236 237 if (!this->m_IsStream[usage]) 238 { 239 return NULL; 240 } 241 242 if (this->m_BufferSide) 243 { 244 side = (ParticleBuffer)(1 - side); 245 } 246 247 return this->m_StreamPtr[usage][side]; 248 } 249 250 //! @brief 指定された属性のパラメータへのポインタを取得します。 251 //! @param[in] usage 利用種別です。 252 //! @return パラメータへのポインタを返します。 GetParameterPtr(ParticleUsage usage)253 const void* GetParameterPtr(ParticleUsage usage) const 254 { 255 NW_ASSERT(usage >= 0 && usage < PARTICLEUSAGE_COUNT); 256 257 if (this->m_IsStream[usage]) 258 { 259 return NULL; 260 } 261 262 return this->m_StreamPtr[usage][0]; 263 } 264 265 //! @brief 指定された属性のパラメータを設定します。 266 //! @details :private 267 //! @param[in] usage 利用種別です。 268 //! @param[in] side バッファの使用目的です。 269 //! @param[in] ptr 新しいパラメータへのポインタです。 270 void SetParameter(ParticleUsage usage, ParticleBuffer side, const f32* ptr); 271 272 //! @brief PARTICLEUSAGE_LIFEのパラメータを設定します。 273 //! @param[in] ptr 新しいパラメータへのポインタです。 SetLifeParameter(const ParticleTime * ptr)274 void SetLifeParameter(const ParticleTime* ptr) 275 { 276 SetParameter(PARTICLEUSAGE_LIFE, PARTICLE_BUFFER_FRONT, (const f32*)ptr); 277 } 278 279 //! @brief 指定された属性のストリームまたはパラメータを取得します。 280 //! @param[in] usage 利用種別です。 281 //! @param[out] stream ストリームの場合にポインタを格納するポインタです。 282 //! @param[out] param パラメータの場合にパラメータを格納するポインタです。 283 //! @param[in] side バッファの使用目的です。 284 //! @return ストリームの場合は、ストリームへのポインタを返します。パラメータの場合はパラメータを返します。 285 template <class T> GetStreamOrParameter(ParticleUsage usage,T ** stream,T * param,ParticleBuffer side)286 NW_FORCE_INLINE bool GetStreamOrParameter(ParticleUsage usage, T** stream, T* param, ParticleBuffer side) 287 { 288 if (this->m_IsStream[usage]) 289 { 290 if (this->m_BufferSide) 291 { 292 side = (ParticleBuffer)(1 - side); 293 } 294 295 *stream = (T*)this->m_StreamPtr[usage][side]; 296 } 297 else 298 { 299 *stream = NULL; 300 if (param != NULL && m_StreamPtr[usage][0] != NULL) 301 { 302 memcpy(param, this->m_StreamPtr[usage][0], sizeof(T)); 303 } 304 } 305 return true; 306 } 307 308 //! @brief 全てのストリームを初期化します。 309 //! @details ストリームの状態を初期化します。この関数は描画中には使用できません。 310 //! GPUからストリームへのアクセスがない状態で使用してください。 311 void Clear(); 312 313 //! @brief 計算用と描画用の対象となるバッファを入れ替えます。 SwapBuffer()314 void SwapBuffer() 315 { 316 ParticleShape* shape = this->m_ParticleShape; 317 318 ParticleBuffer side = PARTICLE_BUFFER_FRONT; 319 if (this->m_BufferSide) 320 { 321 side = (ParticleBuffer)(1 - side); 322 } 323 324 this->m_BufferSide = !this->m_BufferSide; 325 shape->SetBufferSide(this->m_BufferSide); 326 327 int size = this->GetMaxActiveIndex() + 1; 328 for (int usage = 0; usage < PARTICLEUSAGE_COUNT; ++usage) 329 { 330 void* src = this->m_StreamPtr[usage][side]; 331 void* dst = this->m_StreamPtr[usage][(ParticleBuffer)(1 - side)]; 332 333 if (usage != PARTICLEUSAGE_ACTIVEINDEX) 334 { 335 if (src != dst) 336 { 337 nw::os::MemCpy(dst, src, this->m_StreamStride[usage] * size); 338 } 339 } 340 } 341 } 342 343 //! @brief 生成済み全てのパーティクル粒子を削除します。 344 //! @detail 次回の削除処理で実際に削除されます。 345 //! その前に、チャイルドパーティクルの放出処理があれば、終了時として扱われます。 KillParticles()346 void KillParticles() 347 { 348 NW_NULL_ASSERT(m_ParticleSet); 349 ParticleModel* model = static_cast<ParticleModel*>(m_ParticleSet->GetParent()); 350 NW_NULL_ASSERT(model); 351 ParticleTime time = model->ParticleAnimFrameController().GetFrame(); 352 353 u16* activeIndex = (u16*)this->GetStreamPtr( 354 nw::gfx::PARTICLEUSAGE_ACTIVEINDEX,nw::gfx::PARTICLE_BUFFER_FRONT); 355 NW_NULL_ASSERT(activeIndex); 356 357 #ifdef NW_GFX_PARTICLE_COMPAT_1_1 358 ParticleTime* negtime = 359 (ParticleTime*)this->GetStreamPtr(PARTICLEUSAGE_NEG_TIMELIMIT, PARTICLE_BUFFER_FRONT); 360 NW_NULL_ASSERT(negtime); 361 362 for (s32 i = 0; i < m_Count; ++i) 363 { 364 int convertedIndex = activeIndex[i]; 365 366 // -timeで消えるが念のためマージンを設ける 367 negtime[convertedIndex] = -time + 1.0f; 368 } 369 #else 370 ParticleTime* birth = 371 (ParticleTime*)this->GetStreamPtr(PARTICLEUSAGE_BIRTH, PARTICLE_BUFFER_FRONT); 372 NW_NULL_ASSERT(birth); 373 374 ParticleTime lifeParam; 375 if (this->IsStream(PARTICLEUSAGE_LIFE)) 376 { 377 ParticleTime* life = 378 (ParticleTime*)this->GetStreamPtr(PARTICLEUSAGE_LIFE, PARTICLE_BUFFER_FRONT); 379 380 for (s32 i = 0; i < m_Count; ++i) 381 { 382 int convertedIndex = activeIndex[i]; 383 lifeParam = life[convertedIndex]; 384 birth[index] = time - lifeParam - 1; 385 } 386 } 387 else 388 { 389 lifeParam = *(ParticleTime*)this->GetParameterPtr(PARTICLEUSAGE_LIFE); 390 for (s32 i = 0; i < m_Count; ++i) 391 { 392 int convertedIndex = activeIndex[i]; 393 birth[convertedIndex] = time - lifeParam - 1; 394 } 395 } 396 #endif 397 } 398 399 //! @brief 指定したインデックスのパーティクル粒子を削除します。 400 //! @detail 次回の削除処理で実際に削除されます。 401 //! その前に、チャイルドパーティクルの放出処理があれば、終了時として扱われます。 402 //! @param[in] index ACTIVEINDEXが指し示すインデックスです。 KillParticle(int index)403 void KillParticle(int index) 404 { 405 NW_NULL_ASSERT(m_ParticleSet); 406 ParticleModel* model = static_cast<ParticleModel*>(m_ParticleSet->GetParent()); 407 NW_NULL_ASSERT(model); 408 ParticleTime time = model->ParticleAnimFrameController().GetFrame(); 409 410 #ifdef NW_GFX_PARTICLE_COMPAT_1_1 411 ParticleTime* negtime = 412 (ParticleTime*)this->GetStreamPtr(PARTICLEUSAGE_NEG_TIMELIMIT, PARTICLE_BUFFER_FRONT); 413 NW_NULL_ASSERT(negtime); 414 415 negtime[index] = -time + 1.0f; // -timeで消えるが念のためマージンを設ける 416 #else 417 ParticleTime* birth = 418 (ParticleTime*)this->GetStreamPtr(PARTICLEUSAGE_BIRTH, PARTICLE_BUFFER_FRONT); 419 NW_NULL_ASSERT(birth); 420 421 ParticleTime lifeParam; 422 if (this->IsStream(PARTICLEUSAGE_LIFE)) 423 { 424 ParticleTime* life = 425 (ParticleTime*)this->GetStreamPtr(PARTICLEUSAGE_LIFE, PARTICLE_BUFFER_FRONT); 426 lifeParam = life[index]; 427 } 428 else 429 { 430 lifeParam = *(ParticleTime*)this->GetParameterPtr(PARTICLEUSAGE_LIFE); 431 } 432 433 birth[index] = time - lifeParam - 1; 434 #endif 435 } 436 437 //@} 438 439 protected: 440 //---------------------------------------- 441 //! @name コンストラクタ/デストラクタ 442 //@{ 443 444 //! @brief コンストラクタです。 445 ParticleCollection( 446 os::IAllocator* allocator, 447 os::IAllocator* deviceAllocator, 448 void* deviceMemory, 449 ResParticleCollection resObj); 450 451 //! @brief デストラクタです。 452 virtual ~ParticleCollection(); 453 454 //@} 455 private: 456 ParticleAttribute m_ParticleAttribute[PARTICLEUSAGE_COUNT]; 457 int m_Capacity; 458 int m_Count; 459 bool m_BufferSide; 460 bool m_IsStream[PARTICLEUSAGE_COUNT]; 461 void* m_StreamPtr[PARTICLEUSAGE_COUNT][2]; 462 int m_StreamStride[PARTICLEUSAGE_COUNT]; 463 464 u16 m_MinActiveIndex; 465 u16 m_MaxActiveIndex; 466 467 ResParticleCollection m_ResParticleCollection; 468 ParticleShape* m_ParticleShape; 469 ParticleSet* m_ParticleSet; 470 471 os::IAllocator* m_DeviceAllocator; 472 void* m_DeviceMemory; 473 }; 474 475 } // namespace gfx 476 } // namespace nw 477 478 #endif // NW_GFX_PARTICLECOLLECTION_H_ 479