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