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