1 /*---------------------------------------------------------------------------* 2 Project: NintendoWare 3 File: gfx_RenderQueue.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: 28041 $ 14 *---------------------------------------------------------------------------*/ 15 16 #ifndef NW_GFX_RENDERQUEUE_H_ 17 #define NW_GFX_RENDERQUEUE_H_ 18 19 #include <nw/gfx/gfx_RenderElement.h> 20 21 #include <nw/ut/ut_MoveArray.h> 22 #include <nw/ut/ut_Preprocessor.h> 23 #include <nw/ut/ut_TypeTraits.h> 24 #include <nw/gfx/gfx_Camera.h> 25 #include <nw/gfx/gfx_Model.h> 26 #include <nw/gfx/gfx_SkeletalModel.h> 27 #include <nw/gfx/gfx_SceneHelper.h> 28 29 namespace nw 30 { 31 namespace gfx 32 { 33 34 //--------------------------------------------------------------------------- 35 //! @brief 描画要素を格納するキュークラスです。 36 //! 37 //! @tparam TElement 描画単位となるクラスです。 38 //! @tparam TElementList 描画単位のクラスを格納するためのコンテナです。 39 //! @tparam TElementKeyFactory 描画単位をソートするためのキーを作成するクラスです。 40 //--------------------------------------------------------------------------- 41 template< 42 typename TElement, 43 typename TElementList, 44 typename TElementKeyFactory = BasicRenderKeyFactory<typename TElement::KeyType> 45 > 46 class BasicRenderQueue : public GfxObject 47 { 48 private: 49 NW_DISALLOW_COPY_AND_ASSIGN(BasicRenderQueue); 50 NW_STATIC_ASSERT(!ut::IsArray<TElement>::value); 51 52 public: 53 NW_UT_RUNTIME_TYPEINFO; 54 55 static const u8 PRIORITY_END = 0xff; //!< プライオリティの最後(最大値)を表す定義です。 56 57 typedef TElement ElementType; 58 typedef TElementList ElementListType; 59 typedef TElementKeyFactory ElementKeyFactoryType; 60 typedef typename TElement::KeyType ElementKeyType; 61 62 typedef typename TElementList::reference reference; 63 typedef typename TElementList::difference_type difference_type; 64 typedef typename TElementList::value_type value_type; 65 typedef typename TElementList::iterator iterator; 66 typedef typename TElementList::const_iterator const_iterator; 67 68 #if defined(_MSC_VER) && _MSC_VER <= 1201 69 typedef std::reverse_iterator<iterator, TElement> reverse_iterator; 70 typedef std::reverse_iterator<const_iterator, TElement> const_reverse_iterator; 71 #else 72 typedef std::reverse_iterator<iterator> reverse_iterator; 73 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 74 #endif 75 76 //--------------------------------------------------------------------------- 77 //! @brief 描画レイヤーが1(半透明用)のときのみ深度計算を行うための関数オブジェクトです。 78 //--------------------------------------------------------------------------- 79 struct IsCalculatingOnlyLayer1Functor 80 { IsCalculatingOnlyLayer1FunctorIsCalculatingOnlyLayer1Functor81 IsCalculatingOnlyLayer1Functor(Model* model, ResMesh mesh) 82 { 83 isCalculating = 84 model->GetRenderLayerId(mesh) == ResMaterial::TRANSLUCENCY_KIND_LAYER1; 85 } 86 IsCalculatingOnlyLayer1FunctorIsCalculatingOnlyLayer1Functor87 IsCalculatingOnlyLayer1Functor(ResMaterial::TranslucencyKind renderLayer) 88 { 89 isCalculating = renderLayer == ResMaterial::TRANSLUCENCY_KIND_LAYER1; 90 } 91 operatorIsCalculatingOnlyLayer1Functor92 bool operator ()() const 93 { 94 return isCalculating; 95 } 96 97 bool isCalculating; 98 }; 99 100 //--------------------------------------------------------------------------- 101 //! @brief 常に深度計算を行うための関数オブジェクトです。 102 //--------------------------------------------------------------------------- 103 struct AlwaysCalculatingFunctor 104 { AlwaysCalculatingFunctorAlwaysCalculatingFunctor105 AlwaysCalculatingFunctor(Model* model, ResMesh mesh) 106 { NW_UNUSED_VARIABLE(model); NW_UNUSED_VARIABLE(mesh); } 107 AlwaysCalculatingFunctorAlwaysCalculatingFunctor108 AlwaysCalculatingFunctor(ResMaterial::TranslucencyKind renderLayer) 109 { NW_UNUSED_VARIABLE(renderLayer); } 110 operatorAlwaysCalculatingFunctor111 bool operator ()() const 112 { 113 return true; 114 } 115 }; 116 117 //--------------------------------------------------------------------------- 118 //! @brief クリップ座標系での深度を計算する関数オブジェクトです。 119 //--------------------------------------------------------------------------- 120 struct CalculateDepthFunctor 121 { 122 typedef Model ModelType; 123 CalculateDepthFunctorCalculateDepthFunctor124 CalculateDepthFunctor(ModelType* model) 125 : model(model) 126 { 127 NW_NULL_ASSERT(model); 128 this->resModel = model->GetResModel(); 129 NW_ASSERT(resModel.IsValid()); 130 } 131 132 template<typename IsCalculating> operatorCalculateDepthFunctor133 float operator ()(ResMesh mesh, const Camera& camera, IsCalculating isCalculating) const 134 { 135 if (isCalculating()) 136 { 137 ResShape shape = resModel.GetShapes(mesh.GetShapeIndex()); 138 NW_ASSERT(shape.IsValid()); 139 140 return SceneHelper::CalculateDepth( 141 shape.GetCenterPosition(), model->WorldMatrix(), camera); 142 } 143 else 144 { 145 return 0.0f; 146 } 147 } 148 149 ModelType* model; 150 ResModel resModel; 151 }; 152 153 //--------------------------------------------------------------------------- 154 //! @brief スケルタルモデル用のクリップ座標系での深度を計算する関数オブジェクトです。 155 //--------------------------------------------------------------------------- 156 struct CalculateDepthOfSkeletalModelFunctor 157 { 158 typedef SkeletalModel ModelType; 159 CalculateDepthOfSkeletalModelFunctorCalculateDepthOfSkeletalModelFunctor160 CalculateDepthOfSkeletalModelFunctor(ModelType* model) 161 : model(model) 162 { 163 NW_NULL_ASSERT(model); 164 this->resModel = model->GetResModel(); 165 NW_ASSERT(resModel.IsValid()); 166 } 167 168 template<typename IsCalculating> operatorCalculateDepthOfSkeletalModelFunctor169 float operator ()(ResMesh mesh, const Camera& camera, IsCalculating isCalculating) const 170 { 171 if (isCalculating()) 172 { 173 float depth; 174 ResShape shape = resModel.GetShapes(mesh.GetShapeIndex()); 175 NW_ASSERT(shape.IsValid()); 176 177 // プリミティブが1つの場合はボーンのマトリクスを使用する 178 if (shape.GetPrimitiveSetsCount() == 1) 179 { 180 ResPrimitiveSet primitiveSet = shape.GetPrimitiveSets(0); 181 s32 boneIndex = primitiveSet.GetBoneIndexTable(0); 182 Skeleton::MatrixPose& pose = this->model->GetSkeleton()->WorldMatrixPose(); 183 depth = SceneHelper::CalculateDepth( 184 shape.GetCenterPosition(), *pose.GetMatrix(boneIndex), camera); 185 } 186 else 187 { 188 depth = SceneHelper::CalculateDepth( 189 shape.GetCenterPosition(), model->WorldMatrix(), camera); 190 } 191 192 return depth; 193 } 194 else 195 { 196 return 0.0f; 197 } 198 } 199 200 ModelType* model; 201 ResModel resModel; 202 }; 203 204 //--------------------------------------------------------------------------- 205 //! @brief モデルをレンダーキューに追加するための関数オブジェクトです。 206 //--------------------------------------------------------------------------- 207 template<typename ModelType, typename CalculateDepth, typename IsCalculating> 208 struct BasicEnqueueModelFunctor : public std::unary_function<ResMesh, void> 209 { BasicEnqueueModelFunctorBasicEnqueueModelFunctor210 BasicEnqueueModelFunctor( 211 BasicRenderQueue* renderQueue, 212 ModelType* model, 213 u8 layerId, 214 const Camera& camera) 215 : calculateDepth(model), 216 renderQueue(renderQueue), 217 camera(camera), 218 layerId(layerId) {} 219 operatorBasicEnqueueModelFunctor220 result_type operator()(argument_type mesh) 221 { 222 NW_ASSERT(mesh.IsValid()); 223 if (calculateDepth.model->IsMeshVisible(mesh)) 224 { 225 float depth = calculateDepth(mesh, camera, IsCalculating(calculateDepth.model, mesh)); 226 renderQueue->EnqueueMesh(mesh, calculateDepth.model, depth, layerId); 227 } 228 } 229 230 CalculateDepth calculateDepth; 231 BasicRenderQueue* renderQueue; 232 const Camera& camera; 233 u8 layerId; 234 }; 235 236 //! @brief モデルをレンダーキューに追加するための関数オブジェクトです。 237 typedef BasicEnqueueModelFunctor<Model, CalculateDepthFunctor, AlwaysCalculatingFunctor> 238 EnqueueModelFunctor; 239 240 //! @brief スケルタルモデルをレンダーキューに追加するための関数オブジェクトです。 241 typedef BasicEnqueueModelFunctor<SkeletalModel, CalculateDepthOfSkeletalModelFunctor, AlwaysCalculatingFunctor> 242 EnqueueSkeletalModelFunctor; 243 244 //! @brief モデルをレンダーキューに追加するための関数オブジェクトです。 245 //! 描画レイヤーが1(半透明用)のときのみ深度計算を行います。 246 typedef BasicEnqueueModelFunctor<Model, CalculateDepthFunctor, IsCalculatingOnlyLayer1Functor> 247 FastEnqueueModelFunctor; 248 249 //! @brief スケルタルモデルをレンダーキューに追加するための関数オブジェクトです。 250 //! 描画レイヤーが1(半透明用)のときのみ深度計算を行います。 251 typedef BasicEnqueueModelFunctor<SkeletalModel, CalculateDepthOfSkeletalModelFunctor, IsCalculatingOnlyLayer1Functor> 252 FastEnqueueSkeletalModelFunctor; 253 254 //--------------------------------------------------------------------------- 255 //! @brief モデルをレンダーキューに追加するための関数オブジェクトです。 256 //! 257 //! 半透明系のメッシュの深度をモデル単位にしてキーを作成します。 258 //--------------------------------------------------------------------------- 259 template<typename ModelType, typename CalculateDepth, typename IsCalculating> 260 struct BasicEnqueueModelTranslucentModelBaseFunctor : public std::unary_function<ResMesh, void> 261 { BasicEnqueueModelTranslucentModelBaseFunctorBasicEnqueueModelTranslucentModelBaseFunctor262 BasicEnqueueModelTranslucentModelBaseFunctor( 263 BasicRenderQueue* renderQueue, 264 ModelType* model, 265 u8 layerId, 266 const Camera& camera) 267 : calculateDepth(model), 268 renderQueue(renderQueue), 269 camera(camera), 270 layerId(layerId) 271 { 272 NW_NULL_ASSERT(renderQueue); 273 274 modelDepth = SceneHelper::CalculateDepth(model->WorldMatrix(), camera); 275 } 276 operatorBasicEnqueueModelTranslucentModelBaseFunctor277 result_type operator()(argument_type mesh) 278 { 279 NW_ASSERT(mesh.IsValid()); 280 if (calculateDepth.model->IsMeshVisible(mesh)) 281 { 282 ResMaterial::TranslucencyKind translucencyKind = 283 calculateDepth.model->GetRenderLayerId(mesh); 284 285 float depth = (translucencyKind == ResMaterial::TRANSLUCENCY_KIND_OPAQUE) 286 ? calculateDepth(mesh, camera, IsCalculating(translucencyKind)) 287 : modelDepth; 288 289 renderQueue->EnqueueElement( 290 ElementType(mesh, calculateDepth.model), translucencyKind, depth, layerId); 291 } 292 } 293 294 CalculateDepth calculateDepth; 295 BasicRenderQueue* renderQueue; 296 const Camera& camera; 297 float modelDepth; 298 u8 layerId; 299 }; 300 301 //! @brief モデルをレンダーキューに追加するための関数オブジェクトです。 302 typedef BasicEnqueueModelTranslucentModelBaseFunctor<Model, CalculateDepthFunctor, AlwaysCalculatingFunctor> 303 EnqueueModelTranslucentModelBaseFunctor; 304 305 //! @brief スケルタルモデルをレンダーキューに追加するための関数オブジェクトです。 306 typedef BasicEnqueueModelTranslucentModelBaseFunctor<SkeletalModel, CalculateDepthOfSkeletalModelFunctor, AlwaysCalculatingFunctor> 307 EnqueueSkeletalModelTranslucentModelBaseFunctor; 308 309 //! @brief モデルをレンダーキューに追加するための関数オブジェクトです。 310 //! 描画レイヤーが1(半透明用)のときのみ深度計算を行います。 311 typedef BasicEnqueueModelTranslucentModelBaseFunctor<Model, CalculateDepthFunctor, IsCalculatingOnlyLayer1Functor> 312 FastEnqueueModelTranslucentModelBaseFunctor; 313 314 //! @brief スケルタルモデルをレンダーキューに追加するための関数オブジェクトです。 315 //! 描画レイヤーが1(半透明用)のときのみ深度計算を行います。 316 typedef BasicEnqueueModelTranslucentModelBaseFunctor<SkeletalModel, CalculateDepthOfSkeletalModelFunctor, IsCalculatingOnlyLayer1Functor> 317 FastEnqueueSkeletalModelTranslucentModelBaseFunctor; 318 319 //---------------------------------------- 320 //! @name デバッグユーティリティ 321 //@{ 322 323 //! @brief レンダーキューの状態をログ出力にレポートするための関数オブジェクトです。 324 struct ReportFunctor : public std::unary_function<void, reference> 325 { ReportFunctorReportFunctor326 ReportFunctor() : count(0) {} 327 328 //! @brief ログ出力にレポートします。 operatorReportFunctor329 void operator() (reference element) 330 { 331 #ifdef NW_RELEASE 332 NW_UNUSED_VARIABLE(element); 333 #else 334 if (element.IsCommand()) 335 { 336 NW_DEV_LOG("%3d : Command(%x)\n", 337 count, 338 reinterpret_cast<u32>(element.GetCommand())); 339 } 340 else 341 { 342 const ResMesh mesh = element.GetMesh(); 343 const ResModel model = element.GetModel()->GetResModel(); 344 const ResMaterial material = 345 element.GetModel()->GetMaterial(mesh.GetMaterialIndex())->GetOriginal(); 346 NW_DEV_LOG("%3d : Model(%s), Mesh(%s), Material(%s)\n", 347 count, 348 model.GetName(), 349 mesh.GetName(), 350 material.GetName()); 351 } 352 353 ++count; 354 #endif 355 } 356 357 int count; 358 }; 359 360 //@} 361 362 //---------------------------------------- 363 //! @name 作成 364 //@{ 365 366 //! @brief BasicRenderQueue を作成するためのクラスです。 367 //! 368 //! IsFixedSizeMemory の初期値は true です。false に変更すると、各種最大数の設定は無視されます。 369 class Builder 370 { 371 public: 372 //! @brief コンストラクタです。 Builder()373 Builder() : m_IsFixedSizeMemory(true), m_MaxRenderElements(64) {} 374 375 //! @brief デストラクタです。 ~Builder()376 ~Builder() {} 377 378 //! @brief 生成時以外にもメモリを確保するかどうかのフラグを設定します。 379 //! 380 //! true を指定すると、生成時のみ固定サイズのメモリ確保を行います。 381 //! 382 //! false を指定すると、生成時以外にも必要に応じて動的にメモリ確保が行われます。 IsFixedSizeMemory(bool isFixedSizeMemory)383 Builder& IsFixedSizeMemory(bool isFixedSizeMemory) 384 { 385 m_IsFixedSizeMemory = isFixedSizeMemory; 386 return *this; 387 } 388 389 //! @brief キューに積む描画要素の最大数を設定します。 MaxRenderElements(int max)390 Builder& MaxRenderElements(int max) { m_MaxRenderElements = max; return *this; } 391 392 //! @brief レンダーキューを生成します。 393 //! 394 //! @param[in] allocator アロケータです。 395 //! 396 //! @return 生成したレンダーキューを返します。 397 //! Create(os::IAllocator * allocator)398 BasicRenderQueue* Create(os::IAllocator* allocator) 399 { 400 void* queueMemory = allocator->Alloc<BasicRenderQueue>(1); 401 NW_NULL_ASSERT(queueMemory); 402 BasicRenderQueue* queue; 403 if (m_IsFixedSizeMemory) 404 { 405 queue = new(queueMemory) BasicRenderQueue(allocator, m_MaxRenderElements); 406 } 407 else 408 { 409 queue = new(queueMemory) BasicRenderQueue(allocator); 410 } 411 return queue; 412 } 413 414 private: 415 bool m_IsFixedSizeMemory; 416 int m_MaxRenderElements; 417 }; 418 419 //@} 420 421 //---------------------------------------- 422 //! @name キュー操作 423 //@{ 424 425 //! @brief キューに描画要素を追加します。 426 //! 427 //! @param[in] element 追加する描画要素です。 428 //! @param[in] translucencyKind 透明性の種類です。 429 //! @param[in] depth スクリーン座標系におけるメッシュの深度です。(0.0 ~ 1.0) 430 //! @param[in] layerId 描画要素のソート時に最優先に区分される ID です。レイヤーやビューポートの描画を制御するのに用います。 431 //! 432 //! @return 追加された描画要素を返します。追加できなかった場合は NULL が返ります。 433 //! EnqueueElement(const ElementType & element,ResMaterial::TranslucencyKind translucencyKind,float depth,u8 layerId)434 ElementType* EnqueueElement( 435 const ElementType& element, 436 ResMaterial::TranslucencyKind translucencyKind, 437 float depth, 438 u8 layerId) 439 { 440 bool pushed = this->m_List.push_back(element); 441 if (!pushed) 442 { 443 return NULL; 444 } 445 446 ElementType* back = &m_List.back(); 447 448 if (this->m_KeyCachingState == UNUSE_CACHED_KEY || 449 translucencyKind == ResMaterial::TRANSLUCENCY_KIND_LAYER1) 450 { 451 RenderKeyFactory* keyFactory = this->GetKeyFactory(translucencyKind); 452 back->Key() = keyFactory->CreateRenderKey(*back, depth, layerId); 453 } 454 else 455 { 456 if (ut::CheckFlag<u32, u32>(back->GetMesh().GetFlags(), ResMesh::FLAG_VALID_RENDER_KEY_CACHE)) 457 { 458 // キャッシュしたキーを利用します。 459 back->Key() = back->GetMesh().GetRenderKeyCache(); 460 } 461 else 462 { 463 // キーを作成して、キャッシュします。 464 RenderKeyFactory* keyFactory = this->GetKeyFactory(translucencyKind); 465 back->Key() = keyFactory->CreateRenderKey(*back, depth, layerId); 466 467 back->GetMesh().SetRenderKeyCache(back->Key()); 468 back->GetMesh().SetFlags(ut::EnableFlag<u32, u32>( 469 back->GetMesh().GetFlags(), ResMesh::FLAG_VALID_RENDER_KEY_CACHE)); 470 } 471 } 472 473 return back; 474 } 475 476 //! @brief キューにメッシュ要素を追加します。 477 //! 478 //! @param[in] mesh メッシュです。 479 //! @param[in] model メッシュの所有者となるモデルです。 480 //! @param[in] depth スクリーン座標系におけるメッシュの深度です。(0.0 ~ 1.0) 481 //! @param[in] layerId 描画要素のソート時に最優先に区分される ID です。レイヤーやビューポートの描画を制御するのに用います。 482 //! EnqueueMesh(ResMesh mesh,Model * model,float depth,u8 layerId)483 ElementType* EnqueueMesh( 484 ResMesh mesh, 485 Model* model, 486 float depth, 487 u8 layerId) 488 { 489 NW_ASSERT(mesh.IsValid()); 490 NW_NULL_ASSERT(model); 491 492 return EnqueueElement( 493 ElementType(mesh, model), model->GetRenderLayerId(mesh), depth, layerId); 494 } 495 496 //! @brief キューにモデルに含まれるメッシュ要素を追加します。 497 //! 498 //! @param[in] model メッシュの所有者となるモデルです。 499 //! @param[in] layerId 描画要素のソート時に最優先に区分される ID です。レイヤーやビューポートの描画を制御するのに用います。 500 //! @param[in] camera メッシュの深度を計算するのに用いるカメラです。 501 //! EnqueueModel(Model * model,u8 layerId,const Camera & camera)502 void EnqueueModel( 503 Model* model, 504 u8 layerId, 505 const Camera& camera) 506 { 507 NW_NULL_ASSERT(model); 508 gfx::ResMeshArray meshs = model->GetResMeshes(); 509 std::for_each( 510 meshs.begin(), 511 meshs.end(), 512 EnqueueModelFunctor(this, model, layerId, camera)); 513 } 514 515 //! @brief キューにスケルタルモデルに含まれるメッシュ要素を追加します。 516 //! 517 //! @param[in] model メッシュの所有者となるモデルです。 518 //! @param[in] layerId 描画要素のソート時に最優先に区分される ID です。レイヤーやビューポートの描画を制御するのに用います。 519 //! @param[in] camera メッシュの深度を計算するのに用いるカメラです。 520 //! EnqueueSkeletalModel(SkeletalModel * model,u8 layerId,const Camera & camera)521 void EnqueueSkeletalModel( 522 SkeletalModel* model, 523 u8 layerId, 524 const Camera& camera) 525 { 526 NW_NULL_ASSERT(model); 527 gfx::ResMeshArray meshs = model->GetResMeshes(); 528 std::for_each( 529 meshs.begin(), 530 meshs.end(), 531 EnqueueSkeletalModelFunctor(this, model, layerId, camera)); 532 } 533 534 //! @brief キューにコマンド要素を追加します。 535 //! 536 //! ここで設定するコマンドは描画時に呼び出されるので、 537 //! コマンドのインスタンスは描画時まで保持されるようにしてください。 538 //! ローカル変数等を使用して、描画前にデストラクトされると 539 //! 不正な関数呼び出しが行われてしまいます。 540 //! 541 //! @param[in] command 描画時に呼び出されるコマンドです。 542 //! @param[in] translucencyKind 透明性の種類です。 543 //! @param[in] priority メッシュの描画優先度です。 544 //! @param[in] layerId 描画要素のソート時に最優先に区分される ID です。レイヤーやビューポートの描画を制御するのに用います。 545 //! 546 //! @return 追加されたコマンド要素を返します。追加できなかった場合は NULL が返ります。 547 //! EnqueueCommand(RenderCommand * command,ResMaterial::TranslucencyKind translucencyKind,u8 priority,u8 layerId)548 ElementType* EnqueueCommand( 549 RenderCommand* command, 550 ResMaterial::TranslucencyKind translucencyKind, 551 u8 priority, 552 u8 layerId) 553 { 554 RenderKeyFactory* keyFactory = this->GetKeyFactory(translucencyKind); 555 556 bool pushed = this->m_List.push_back( 557 ElementType(keyFactory->CreateCommandRenderKey( 558 command, translucencyKind, priority, layerId))); 559 560 if (pushed) 561 { 562 return &this->m_List.back(); 563 } 564 else 565 { 566 return NULL; 567 } 568 } 569 570 //! @brief キューの全ての要素を削除します。 571 //! 572 //! @param[in] cacheEnabled true を指定するとキャッシュ機能を有効にします。 573 //! 574 void Reset(bool cacheEnabled = false) 575 { 576 this->m_List.clear(); 577 this->m_KeyCachingState = (cacheEnabled) ? USE_CACHED_KEY : UNUSE_CACHED_KEY; 578 } 579 580 //! @brief キューの全ての要素を削除して、キーファクトリの設定を行います。 581 //! 582 //! 各キーファクトリに NULL を設定すると、ファクトリの変更を行いません。 583 //! 584 //! @param[in] opacityKeyFactory 不透明メッシュのキーファクトリです。 585 //! @param[in] translucentKeyFactory 半透明メッシュのキーファクトリです。 586 //! @param[in] additiveKeyFactory 加算合成メッシュのキーファクトリです。 587 //! @param[in] subtractionKeyFactory 減算合成メッシュのキーファクトリです。 588 //! @param[in] cacheEnabled true を指定するとキャッシュ機能を有効にします。 589 //! 590 //! @sa nw::gfx::CreatePriorMaterialRenderKeyFactory 591 //! @sa nw::gfx::CreatePriorMaterialReverseDepthRenderKeyFactory 592 //! @sa nw::gfx::CreatePriorMaterialAndZeroDepthRenderKeyFactory 593 //! @sa nw::gfx::CreatePriorDepthRenderKeyFactory 594 //! @sa nw::gfx::CreatePriorDepthReverseDepthRenderKeyFactory 595 //! @sa nw::gfx::CreateTopPriorDepthRenderKeyFactory 596 //! @sa nw::gfx::CreateTopPriorDepthReverseDepthRenderKeyFactory 597 //! 598 void Reset( 599 ElementKeyFactoryType* opacityKeyFactory, 600 ElementKeyFactoryType* translucentKeyFactory, 601 ElementKeyFactoryType* additiveKeyFactory, 602 ElementKeyFactoryType* subtractionKeyFactory, 603 bool cacheEnabled = false) 604 { 605 this->Reset(cacheEnabled); 606 607 if (opacityKeyFactory != NULL) 608 { 609 this->m_OpacityKeyFactory = opacityKeyFactory; 610 } 611 if (translucentKeyFactory != NULL) 612 { 613 this->m_TranslucentKeyFactory = translucentKeyFactory; 614 } 615 if (additiveKeyFactory != NULL) 616 { 617 this->m_AdditiveKeyFactory = additiveKeyFactory; 618 } 619 if (subtractionKeyFactory != NULL) 620 { 621 this->m_SubtractionKeyFactory = subtractionKeyFactory; 622 } 623 } 624 625 //@} 626 627 //---------------------------------------- 628 //! @name 取得/設定 629 //@{ 630 631 //! @brief 要素数を取得します。 Size()632 int Size() const 633 { 634 return m_List.size(); 635 } 636 637 //! @brief 要素が1つもない場合は true を返します。 Empty()638 bool Empty() const 639 { 640 return m_List.empty(); 641 } 642 643 //! @brief 先頭の要素を参照します。 Peek()644 ElementType& Peek() 645 { 646 return m_List.front(); 647 } 648 649 //! @brief 先頭の要素を参照します。 Peek()650 const ElementType& Peek() const 651 { 652 return m_List.front(); 653 } 654 655 //! @brief 先頭のイテレータを取得します。 Begin()656 iterator Begin() 657 { 658 return m_List.begin(); 659 } 660 661 //! @brief 先頭のイテレータを取得します。 Begin()662 const_iterator Begin() const 663 { 664 return m_List.begin(); 665 } 666 667 //! @brief 末尾のイテレータを取得します。 End()668 iterator End() 669 { 670 return m_List.end(); 671 } 672 673 //! @brief 末尾のイテレータを取得します。 End()674 const_iterator End() const 675 { 676 return m_List.end(); 677 } 678 679 //! @brief 先頭のリバースイテレータを取得します。 ReverseBegin()680 reverse_iterator ReverseBegin() 681 { 682 return m_List.rbegin(); 683 } 684 685 //! @brief 先頭のリバースイテレータを取得します。 ReverseBegin()686 const_reverse_iterator ReverseBegin() const 687 { 688 return m_List.rbegin(); 689 } 690 691 //! @brief 末尾のリバースイテレータを取得します。 ReverseEnd()692 reverse_iterator ReverseEnd() 693 { 694 return m_List.rend(); 695 } 696 697 //! @brief 末尾のリバースイテレータを取得します。 ReverseEnd()698 const_reverse_iterator ReverseEnd() const 699 { 700 return m_List.rend(); 701 } 702 703 //@} 704 705 private: BasicRenderQueue(os::IAllocator * allocator)706 explicit BasicRenderQueue(os::IAllocator* allocator) 707 : GfxObject(allocator), 708 m_List(allocator), 709 m_OpacityKeyFactory(NULL), 710 m_TranslucentKeyFactory(NULL), 711 m_AdditiveKeyFactory(NULL), 712 m_SubtractionKeyFactory(NULL), 713 m_KeyCachingState(UNUSE_CACHED_KEY) {} 714 BasicRenderQueue(os::IAllocator * allocator,int maxRenderElements)715 BasicRenderQueue(os::IAllocator* allocator, int maxRenderElements) 716 : GfxObject(allocator), 717 m_List(maxRenderElements, allocator), 718 m_OpacityKeyFactory(NULL), 719 m_TranslucentKeyFactory(NULL), 720 m_AdditiveKeyFactory(NULL), 721 m_SubtractionKeyFactory(NULL), 722 m_KeyCachingState(UNUSE_CACHED_KEY) {} 723 ~BasicRenderQueue()724 virtual ~BasicRenderQueue() {} 725 GetKeyFactory(ResMaterial::TranslucencyKind translucencyKind)726 ElementKeyFactoryType* GetKeyFactory(ResMaterial::TranslucencyKind translucencyKind) 727 { 728 ElementKeyFactoryType* keyFactory = NULL; 729 switch (translucencyKind) 730 { 731 case ResMaterial::TRANSLUCENCY_KIND_LAYER0: 732 keyFactory = this->m_OpacityKeyFactory; 733 break; 734 case ResMaterial::TRANSLUCENCY_KIND_LAYER1: 735 keyFactory = this->m_TranslucentKeyFactory; 736 break; 737 case ResMaterial::TRANSLUCENCY_KIND_LAYER2: 738 keyFactory = this->m_SubtractionKeyFactory; 739 break; 740 case ResMaterial::TRANSLUCENCY_KIND_LAYER3: 741 keyFactory = this->m_AdditiveKeyFactory; 742 break; 743 default: NW_FAILSAFE_IF(false) { keyFactory = this->m_OpacityKeyFactory; } break; 744 } 745 NW_NULL_ASSERT(keyFactory); 746 return keyFactory; 747 } 748 749 TElementList m_List; 750 ElementKeyFactoryType* m_OpacityKeyFactory; 751 ElementKeyFactoryType* m_TranslucentKeyFactory; 752 ElementKeyFactoryType* m_AdditiveKeyFactory; 753 ElementKeyFactoryType* m_SubtractionKeyFactory; 754 755 enum KeyCachingState 756 { 757 UNUSE_CACHED_KEY, 758 USE_CACHED_KEY 759 }; 760 761 KeyCachingState m_KeyCachingState; 762 }; 763 764 //! @brief 標準のレンダーキューの定義です。 765 typedef BasicRenderQueue< 766 BasicRenderElement<RenderKeyType>, 767 ut::MoveArray<BasicRenderElement<RenderKeyType> > > 768 RenderQueue; 769 770 //--------------------------------------------------------------------------- 771 //! @brief ソート比較用関数オブジェクトです。 772 //--------------------------------------------------------------------------- 773 struct RenderElementCompare 774 : public std::binary_function<RenderElement, RenderElement, bool> 775 { operatorRenderElementCompare776 bool operator() ( 777 const RenderElement& lhs, 778 const RenderElement& rhs) 779 { 780 return lhs.Key() < rhs.Key(); 781 } 782 }; 783 784 } // namespace gfx 785 } // namespace nw 786 787 #endif // NW_GFX_RENDERQUEUE_H_ 788