1 /*---------------------------------------------------------------------------* 2 Project: NintendoWare 3 File: gfx_ParticleShape.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_PARTICLESHAPE_H_ 19 #define NW_GFX_PARTICLESHAPE_H_ 20 21 #include <nw/gfx/gfx_SceneObject.h> 22 #include <nw/gfx/res/gfx_ResParticleShape.h> 23 #include <nw/gfx/res/gfx_ResParticleUpdater.h> 24 25 namespace nw 26 { 27 namespace gfx 28 { 29 class ParticleShape; 30 class ParticleSet; 31 32 //! @brief パーティクルのバッファの種別です。 33 enum ParticleBuffer 34 { 35 PARTICLE_BUFFER_FRONT = 0, //!< 最新の情報が格納されているバッファです。 36 PARTICLE_BUFFER_BACK //!< ダブルバッファ処理の交換用バッファです。 37 }; 38 39 //--------------------------------------------------------------------------- 40 //! @brief パーティクルのためのシェイプを表すクラスです。 41 //! @details ParticleCollectionを使い、このクラスは利用しないようにしてください。 42 //--------------------------------------------------------------------------- 43 class ParticleShape : public SceneObject 44 { 45 private: 46 NW_DISALLOW_COPY_AND_ASSIGN(ParticleShape); 47 48 public: 49 NW_UT_RUNTIME_TYPEINFO; 50 51 //! @brief パーティクルのための頂点バッファ情報です。 52 //! @details :private 53 struct VertexAttribute 54 { 55 s32 m_Usage; 56 u32 m_FormatType; 57 u8 m_Dimension; 58 bool m_IsStream; 59 u8* m_Stream[2]; 60 void* m_CommandPtr[2]; //< コマンド上でのこのデータの先頭アドレス 61 }; 62 63 //---------------------------------------- 64 //! @name 作成 65 //@{ 66 67 //! @brief リソースからパーティクルシェイプノードを生成します。 68 //! 69 //! @param[in] resource リソースです。 70 //! @param[in] capacity 最大頂点数です。 71 //! @param[in] mainAllocator メインメモリのアロケータです。 72 //! @param[in] deviceAllocator デバイスメモリのアロケータです。 73 //! 74 //! @return 生成されたトランスフォームノードです。 75 //! 76 static ParticleShape* Create( 77 ResSceneObject resource, 78 int capacity, 79 os::IAllocator* mainAllocator, 80 os::IAllocator* deviceAllocator); 81 82 //! @brief 生成時に必要なメモリサイズを取得します。 83 //! @param[in] capacity 最大頂点数です。 84 //! @param[in] alignment 計算に用いるアライメントです。2 のべき乗である必要があります。 85 //! @return 必要なメモリサイズです。 86 static size_t GetMemorySize( 87 int capacity, 88 size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) 89 { 90 os::MemorySizeCalculator size(alignment); 91 92 GetMemorySizeInternal(&size, capacity); 93 94 return size.GetSizeWithPadding(alignment); 95 } 96 97 //! @details :private 98 static void GetMemorySizeInternal( 99 os::MemorySizeCalculator* pSize, 100 int capacity); 101 102 //! @brief 生成時に必要なデバイスメモリサイズを取得します。 103 //! @param[in] capacity 最大頂点数です。 104 //! @param[in] alignment 計算に用いるアライメントです。2 のべき乗である必要があります。 105 //! @return 必要なデバイスメモリサイズです。 106 static size_t GetDeviceMemorySize( 107 int capacity, 108 size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) 109 { 110 os::MemorySizeCalculator size(alignment); 111 112 GetDeviceMemorySizeInternal(&size, capacity); 113 114 return size.GetSizeWithPadding(alignment); 115 } 116 117 //! @details :private 118 static void GetDeviceMemorySizeInternal( 119 os::MemorySizeCalculator* pSize, 120 int capacity); 121 122 //! @details :private 123 static int AddVertexStreamSize( 124 u32 formatType, 125 int dimension, 126 int capacity, 127 int prevSize); 128 129 //! @details :private 130 static int AddVertexParamSize( 131 u32 formatType, 132 int dimension, 133 int prevSize); 134 135 //! @details :private 136 VertexAttribute* AddVertexStream( 137 s32 usage, 138 u32 formatType, 139 int dimension, 140 int capacity, 141 u8** memory); 142 143 //! @details :private 144 VertexAttribute* AddVertexParam( 145 s32 usage, 146 u32 formatType, 147 int dimension, 148 f32* parameters, 149 u8** memory); 150 151 //@} 152 153 //---------------------------------------- 154 //! @name 取得/設定 155 //@{ 156 157 //! @brief リソースを取得します。 158 //! @return パーティクルシェイプのリソースです。 GetResParticleShape()159 ResParticleShape GetResParticleShape() 160 { 161 return ResDynamicCast<ResParticleShape>( this->GetResSceneObject() ); 162 } 163 164 //! @brief リソースを取得します。 165 //! @return パーティクルシェイプのリソースです。 GetResParticleShape()166 const ResParticleShape GetResParticleShape() const 167 { 168 return ResDynamicCast<ResParticleShape>( this->GetResSceneObject() ); 169 } 170 171 //! @brief 頂点アトリビュートの個数を取得します。 172 //! @return 頂点アトリビュートの個数です。 GetVertexAttributesCount()173 int GetVertexAttributesCount() const 174 { 175 return this->m_ResVertexAttributeDataCount; 176 } 177 178 //! @brief 頂点アトリビュートがストリームかどうかを調べます。 179 //! @param[in] index インデックスです。 180 //! @return 頂点アトリビュートがストリームの場合はtrueを返します。 IsVertexStream(int index)181 bool IsVertexStream(int index) 182 { 183 NW_ASSERT(index >= 0 && index < this->m_ResVertexAttributeDataCount); 184 return this->m_VertexAttribute[index].m_IsStream; 185 } 186 187 //! @brief 頂点アトリビュートの利用種別を取得します。 188 //! @param[in] index インデックスです。 189 //! @return 頂点アトリビュートの利用種別です。 GetVertexAttributeUsage(int index)190 s32 GetVertexAttributeUsage(int index) 191 { 192 NW_ASSERT(index >= 0 && index < this->m_ResVertexAttributeDataCount); 193 return this->m_VertexAttribute[index].m_Usage; 194 } 195 196 //! @brief 頂点アトリビュートのフォーマットを取得します。 197 //! @param[in] index インデックスです。 198 //! @return 頂点アトリビュートのフォーマットです。 GetVertexAttributeFormatType(int index)199 u32 GetVertexAttributeFormatType(int index) 200 { 201 NW_ASSERT(index >= 0 && index < this->m_ResVertexAttributeDataCount); 202 return this->m_VertexAttribute[index].m_FormatType; 203 } 204 205 //! @brief 頂点アトリビュートの次元を取得します。 206 //! @param[in] index インデックスです。 207 //! @return 頂点アトリビュートの次元です。 GetVertexAttributeDimension(int index)208 u8 GetVertexAttributeDimension(int index) 209 { 210 NW_ASSERT(index >= 0 && index < this->m_ResVertexAttributeDataCount); 211 return this->m_VertexAttribute[index].m_Dimension; 212 } 213 214 //! @brief 頂点アトリビュートのストリームのポインタを取得します。 215 //! @param[in] index インデックスです。 216 //! @param[in] side バッファの使用目的です。 217 //! @return 頂点アトリビュートのストリームへのポインタです。 GetVertexStreamPtr(int index,ParticleBuffer side)218 u8* GetVertexStreamPtr(int index, ParticleBuffer side) 219 { 220 NW_ASSERT(index >= 0 && index < this->m_ResVertexAttributeDataCount); 221 NW_ASSERT(side >= 0 && side <= 1); 222 if (!this->m_VertexAttribute[index].m_IsStream) 223 { 224 return NULL; 225 } 226 227 if (this->m_BufferSide) 228 { 229 side = (ParticleBuffer)(1 - side); 230 } 231 232 return this->m_VertexAttribute[index].m_Stream[side]; 233 } 234 235 //! @brief 頂点アトリビュートのストリームのポインタを取得します。 236 //! @param[in] index インデックスです。 237 //! @param[in] side バッファの使用目的です。 238 //! @return 頂点アトリビュートのストリームへのポインタです。 GetVertexStreamPtr(int index,ParticleBuffer side)239 const u8* GetVertexStreamPtr(int index, ParticleBuffer side) const 240 { 241 NW_ASSERT(index >= 0 && index < this->m_ResVertexAttributeDataCount); 242 NW_ASSERT(side >= 0 && side <= 1); 243 if (!this->m_VertexAttribute[index].m_IsStream) 244 { 245 return NULL; 246 } 247 248 if (this->m_BufferSide) 249 { 250 side = (ParticleBuffer)(1 - side); 251 } 252 253 return this->m_VertexAttribute[index].m_Stream[side]; 254 } 255 256 //! @brief 頂点アトリビュートのパラメータを取得します。 257 //! @param[in] index インデックスです。 258 //! @return 頂点アトリビュートのストリームへのポインタです。 GetVertexParameter(int index)259 f32* GetVertexParameter(int index) 260 { 261 NW_ASSERT(index >= 0 && index < this->m_ResVertexAttributeDataCount); 262 if (this->m_VertexAttribute[index].m_IsStream) 263 { 264 return NULL; 265 } 266 267 return reinterpret_cast<f32*>(this->m_VertexAttribute[index].m_Stream[0]); 268 } 269 270 //! @brief 頂点アトリビュートのパラメータを取得します。 271 //! @param[in] index インデックスです。 272 //! @return 頂点アトリビュートのストリームへのポインタです。 GetVertexParameter(int index)273 const f32* GetVertexParameter(int index) const 274 { 275 NW_ASSERT(index >= 0 && index < this->m_ResVertexAttributeDataCount); 276 if (this->m_VertexAttribute[index].m_IsStream) 277 { 278 return NULL; 279 } 280 281 return reinterpret_cast<const f32*>(this->m_VertexAttribute[index].m_Stream[0]); 282 } 283 284 //! @brief 頂点アトリビュートのパラメータを設定します。 285 //! @details :private 286 //! @param[in] index インデックスです。 287 //! @param[in] side バッファの使用目的です。 288 //! @param[in] ptr 新しいパラメータへのポインタです。 SetVertexParameter(int index,ParticleBuffer side,const f32 * ptr)289 void SetVertexParameter(int index, ParticleBuffer side, const f32* ptr) 290 { 291 NW_ASSERT(index >= 0 && index < this->m_ResVertexAttributeDataCount); 292 NW_ASSERT(side >= 0 && side <= 1); 293 if (this->m_VertexAttribute[index].m_IsStream) 294 { 295 return; 296 } 297 298 if (this->m_BufferSide) 299 { 300 side = (ParticleBuffer)(1 - side); 301 } 302 303 int count = this->GetVertexAttributeDimension(index); 304 f32* fdata = this->GetVertexParameter(index); 305 306 u32 data[4] = { 0, 0, 0, 0 }; 307 308 for (int j = 0; j < count; ++j) 309 { 310 fdata[j] = ptr[j]; 311 data[j] = ut::Float24::Float32ToBits24(fdata[j]); 312 } 313 314 u32* target = reinterpret_cast<u32*>( 315 this->m_VertexAttribute[index].m_CommandPtr[side]); 316 317 *target++ = (data[3] << 8) | (data[2] >> 16); 318 *target++ = (data[2] << 16) | (data[1] >> 8); 319 *target = (data[1] << 24) | (data[0]); 320 } 321 322 //! :private SetVertexAttributeCommandPtr(int index,int side,void * ptr)323 void* SetVertexAttributeCommandPtr(int index, int side, void* ptr) 324 { 325 NW_ASSERT(index >= 0 && index < this->m_ResVertexAttributeDataCount); 326 NW_ASSERT(side >= 0 && side <= 1); 327 return this->m_VertexAttribute[index].m_CommandPtr[side] = ptr; 328 } 329 330 //! @brief プリミティブのストリームのポインタを取得します。 331 //! @param[in] side バッファの使用目的です。 332 //! @return プリミティブのストリームへのポインタです。 GetPrimitiveStreamPtr(ParticleBuffer side)333 u8* GetPrimitiveStreamPtr(ParticleBuffer side) 334 { 335 NW_ASSERT(side >= 0 && side <= 1); 336 if (this->m_BufferSide) 337 { 338 side = (ParticleBuffer)(1 - side); 339 } 340 return this->m_PrimitiveBuffer[side]; 341 } 342 343 //! @brief プリミティブのストリームのポインタを取得します。 344 //! @param[in] side バッファの使用目的です。 345 //! @return プリミティブのストリームへのポインタです。 GetPrimitiveStreamPtr(ParticleBuffer side)346 const u8* GetPrimitiveStreamPtr(ParticleBuffer side) const 347 { 348 NW_ASSERT(side >= 0 && side <= 1); 349 if (this->m_BufferSide) 350 { 351 side = (ParticleBuffer)(1 - side); 352 } 353 return this->m_PrimitiveBuffer[side]; 354 } 355 356 //! @brief GPUコマンド発行のためのプリミティブのストリームのオフセットを取得します。 357 //! @details :private 358 //! @param[in] side バッファの使用目的です。 359 //! @return プリミティブのストリームへのポインタです。 GetPrimitiveStreamOffset(ParticleBuffer side)360 u32 GetPrimitiveStreamOffset(ParticleBuffer side) const 361 { 362 NW_ASSERT(side >= 0 && side <= 1); 363 if (this->m_BufferSide) 364 { 365 side = (ParticleBuffer)(1 - side); 366 } 367 return this->m_PrimitiveBufferOffset[side]; 368 } 369 370 //! @brief 各ストリームに格納できるパーティクル数の上限を取得します。 371 //! @return パーティクル数の上限です。 GetVertexCapacity()372 int GetVertexCapacity() const 373 { 374 return m_Capacity; 375 } 376 377 //! @brief 計算用と描画用の対象となるバッファを入れ替えます。 SetBufferSide(bool swap)378 void SetBufferSide(bool swap) 379 { 380 this->m_BufferSide = swap; 381 } 382 383 //! @brief 表面のバッファ番号を取得します。 384 //! @return 表面のバッファ番号です。 GetBufferSide()385 int GetBufferSide() const 386 { 387 return this->m_BufferSide ? 1 : 0; 388 } 389 390 //! @brief コマンドキャッシュを生成します。 391 //! @details :private 392 void CreateCommandCache(ParticleSet* particleSet); 393 394 //! @brief バッファをフラッシュします。 395 //! @details :private 396 void FlushBuffer(); 397 398 //@} 399 400 void* m_CommandCache[2]; 401 s32 m_CommandCacheSize[2]; 402 403 void* m_DeactivateVertexCommandCache; 404 s32 m_DeactivateVertexCommandCacheSize; 405 406 void* m_PrimitiveCommandCache; 407 s32 m_PrimitiveCommandCacheSize; 408 409 protected: 410 //---------------------------------------- 411 //! @name コンストラクタ/デストラクタ 412 //@{ 413 414 //! コンストラクタです。 415 ParticleShape( 416 int capacity, 417 os::IAllocator* allocator, 418 os::IAllocator* deviceAllocator, 419 void* deviceMemory, 420 ResParticleShape resObj); 421 422 //! デストラクタです。 423 virtual ~ParticleShape(); 424 425 //@} 426 427 private: 428 //! @brief アトリビュートを追加します。 429 //! @details :private AddVertexAttribute(s32 usage,u32 formatType,u8 dimension,bool isStream,u8 * stream0,u8 * stream1)430 VertexAttribute* AddVertexAttribute( 431 s32 usage, 432 u32 formatType, 433 u8 dimension, 434 bool isStream, 435 u8* stream0, 436 u8* stream1) 437 { 438 this->m_VertexAttribute[this->m_ResVertexAttributeDataCount].m_Usage = usage; 439 this->m_VertexAttribute[this->m_ResVertexAttributeDataCount].m_FormatType = formatType; 440 this->m_VertexAttribute[this->m_ResVertexAttributeDataCount].m_Dimension = dimension; 441 this->m_VertexAttribute[this->m_ResVertexAttributeDataCount].m_IsStream = isStream; 442 this->m_VertexAttribute[this->m_ResVertexAttributeDataCount].m_Stream[0] = stream0; 443 this->m_VertexAttribute[this->m_ResVertexAttributeDataCount].m_Stream[1] = stream1; 444 this->m_VertexAttribute[this->m_ResVertexAttributeDataCount].m_CommandPtr[0] = NULL; 445 this->m_VertexAttribute[this->m_ResVertexAttributeDataCount].m_CommandPtr[1] = NULL; 446 ++this->m_ResVertexAttributeDataCount; 447 return &this->m_VertexAttribute[this->m_ResVertexAttributeDataCount - 1]; 448 } 449 450 static const int bufferAlignment = 4; // ストリームに必要なアライメント 451 int m_Capacity; 452 bool m_BufferSide; 453 454 int m_ResVertexAttributeDataCount; 455 VertexAttribute m_VertexAttribute[PARTICLEUSAGE_COUNT]; 456 457 u8* m_PrimitiveBuffer[2]; 458 u32 m_PrimitiveBufferOffset[2]; 459 460 os::IAllocator* m_DeviceAllocator; 461 void* m_DeviceMemory; 462 }; 463 464 } // namespace gfx 465 } // namespace nw 466 467 #endif // NW_GFX_PARTICLESET_H_ 468