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