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: 25569 $
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     //!
EnqueueElement(const ElementType & element,ResMaterial::TranslucencyKind translucencyKind,float depth,u8 layerId)432     ElementType* EnqueueElement(
433         const ElementType& element,
434         ResMaterial::TranslucencyKind translucencyKind,
435         float depth,
436         u8 layerId)
437     {
438         this->m_List.push_back(element);
439         ElementType* back = &m_List.back();
440         NW_NULL_ASSERT(back);
441 
442         if (this->m_KeyCachingState == UNUSE_CACHED_KEY ||
443             translucencyKind == ResMaterial::TRANSLUCENCY_KIND_LAYER1)
444         {
445             RenderKeyFactory* keyFactory = this->GetKeyFactory(translucencyKind);
446             back->Key() = keyFactory->CreateRenderKey(*back, depth, layerId);
447         }
448         else
449         {
450             if (ut::CheckFlag<u32, u32>(back->GetMesh().GetFlags(), ResMesh::FLAG_VALID_RENDER_KEY_CACHE))
451             {
452                 // キャッシュしたキーを利用します。
453                 back->Key() = back->GetMesh().GetRenderKeyCache();
454             }
455             else
456             {
457                 // キーを作成して、キャッシュします。
458                 RenderKeyFactory* keyFactory = this->GetKeyFactory(translucencyKind);
459                 back->Key() = keyFactory->CreateRenderKey(*back, depth, layerId);
460 
461                 back->GetMesh().SetRenderKeyCache(back->Key());
462                 back->GetMesh().SetFlags(ut::EnableFlag<u32, u32>(
463                     back->GetMesh().GetFlags(), ResMesh::FLAG_VALID_RENDER_KEY_CACHE));
464             }
465         }
466 
467         return back;
468     }
469 
470     //! @brief キューにメッシュ要素を追加します。
471     //!
472     //! @param[in]    mesh メッシュです。
473     //! @param[in]    model メッシュの所有者となるモデルです。
474     //! @param[in]    depth スクリーン座標系におけるメッシュの深度です。(0.0 ~ 1.0)
475     //! @param[in]    layerId 描画要素のソート時に最優先に区分される ID です。レイヤーやビューポートの描画を制御するのに用います。
476     //!
EnqueueMesh(ResMesh mesh,Model * model,float depth,u8 layerId)477     ElementType* EnqueueMesh(
478         ResMesh mesh,
479         Model* model,
480         float depth,
481         u8 layerId)
482     {
483         NW_ASSERT(mesh.IsValid());
484         NW_NULL_ASSERT(model);
485 
486         return EnqueueElement(
487             ElementType(mesh, model), model->GetRenderLayerId(mesh), depth, layerId);
488     }
489 
490     //! @brief キューにモデルに含まれるメッシュ要素を追加します。
491     //!
492     //! @param[in]    model メッシュの所有者となるモデルです。
493     //! @param[in]    layerId 描画要素のソート時に最優先に区分される ID です。レイヤーやビューポートの描画を制御するのに用います。
494     //! @param[in]    camera メッシュの深度を計算するのに用いるカメラです。
495     //!
EnqueueModel(Model * model,u8 layerId,const Camera & camera)496     void EnqueueModel(
497         Model* model,
498         u8 layerId,
499         const Camera& camera)
500     {
501         NW_NULL_ASSERT(model);
502         gfx::ResMeshArray meshs = model->GetResMeshes();
503         std::for_each(
504             meshs.begin(),
505             meshs.end(),
506             EnqueueModelFunctor(this, model, layerId, camera));
507     }
508 
509     //! @brief キューにスケルタルモデルに含まれるメッシュ要素を追加します。
510     //!
511     //! @param[in]    model メッシュの所有者となるモデルです。
512     //! @param[in]    layerId 描画要素のソート時に最優先に区分される ID です。レイヤーやビューポートの描画を制御するのに用います。
513     //! @param[in]    camera メッシュの深度を計算するのに用いるカメラです。
514     //!
EnqueueSkeletalModel(SkeletalModel * model,u8 layerId,const Camera & camera)515     void EnqueueSkeletalModel(
516         SkeletalModel* model,
517         u8 layerId,
518         const Camera& camera)
519     {
520         NW_NULL_ASSERT(model);
521         gfx::ResMeshArray meshs = model->GetResMeshes();
522         std::for_each(
523             meshs.begin(),
524             meshs.end(),
525             EnqueueSkeletalModelFunctor(this, model, layerId, camera));
526     }
527 
528     //! @brief キューにコマンド要素を追加します。
529     //!
530     //! ここで設定するコマンドは描画時に呼び出されるので、
531     //! コマンドのインスタンスは描画時まで保持されるようにしてください。
532     //! ローカル変数等を使用して、描画前にデストラクトされると
533     //! 不正な関数呼び出しが行われてしまいます。
534     //!
535     //! @param[in]    command 描画時に呼び出されるコマンドです。
536     //! @param[in]    translucencyKind 透明性の種類です。
537     //! @param[in]    priority メッシュの描画優先度です。
538     //! @param[in]    layerId 描画要素のソート時に最優先に区分される ID です。レイヤーやビューポートの描画を制御するのに用います。
539     //!
EnqueueCommand(RenderCommand * command,ResMaterial::TranslucencyKind translucencyKind,u8 priority,u8 layerId)540     ElementType* EnqueueCommand(
541         RenderCommand* command,
542         ResMaterial::TranslucencyKind translucencyKind,
543         u8 priority,
544         u8 layerId)
545     {
546         RenderKeyFactory* keyFactory = this->GetKeyFactory(translucencyKind);
547 
548         this->m_List.push_back(
549             ElementType(keyFactory->CreateCommandRenderKey(
550                 command, translucencyKind, priority, layerId)));
551 
552         return &this->m_List.back();
553     }
554 
555     //! @brief キューの全ての要素を削除します。
556     //!
557     //! @param[in] cacheEnabled true を指定するとキャッシュ機能を有効にします。
558     //!
559     void Reset(bool cacheEnabled = false)
560     {
561         this->m_List.clear();
562         this->m_KeyCachingState = (cacheEnabled) ? USE_CACHED_KEY : UNUSE_CACHED_KEY;
563     }
564 
565     //! @brief キューの全ての要素を削除して、キーファクトリの設定を行います。
566     //!
567     //! 各キーファクトリに NULL を設定すると、ファクトリの変更を行いません。
568     //!
569     //! @param[in] opacityKeyFactory 不透明メッシュのキーファクトリです。
570     //! @param[in] translucentKeyFactory 半透明メッシュのキーファクトリです。
571     //! @param[in] additiveKeyFactory 加算合成メッシュのキーファクトリです。
572     //! @param[in] subtractionKeyFactory 減算合成メッシュのキーファクトリです。
573     //! @param[in] cacheEnabled true を指定するとキャッシュ機能を有効にします。
574     //!
575     //! @sa nw::gfx::CreatePriorMaterialRenderKeyFactory
576     //! @sa nw::gfx::CreatePriorMaterialReverseDepthRenderKeyFactory
577     //! @sa nw::gfx::CreatePriorMaterialAndZeroDepthRenderKeyFactory
578     //! @sa nw::gfx::CreatePriorDepthRenderKeyFactory
579     //! @sa nw::gfx::CreatePriorDepthReverseDepthRenderKeyFactory
580     //! @sa nw::gfx::CreateTopPriorDepthRenderKeyFactory
581     //! @sa nw::gfx::CreateTopPriorDepthReverseDepthRenderKeyFactory
582     //!
583     void Reset(
584         ElementKeyFactoryType* opacityKeyFactory,
585         ElementKeyFactoryType* translucentKeyFactory,
586         ElementKeyFactoryType* additiveKeyFactory,
587         ElementKeyFactoryType* subtractionKeyFactory,
588         bool cacheEnabled = false)
589     {
590         this->Reset(cacheEnabled);
591 
592         if (opacityKeyFactory != NULL)
593         {
594             this->m_OpacityKeyFactory = opacityKeyFactory;
595         }
596         if (translucentKeyFactory != NULL)
597         {
598             this->m_TranslucentKeyFactory = translucentKeyFactory;
599         }
600         if (additiveKeyFactory != NULL)
601         {
602             this->m_AdditiveKeyFactory = additiveKeyFactory;
603         }
604         if (subtractionKeyFactory != NULL)
605         {
606             this->m_SubtractionKeyFactory = subtractionKeyFactory;
607         }
608     }
609 
610     //@}
611 
612     //----------------------------------------
613     //! @name 取得/設定
614     //@{
615 
616     //! @brief 要素数を取得します。
Size()617     int Size() const
618     {
619         return m_List.size();
620     }
621 
622     //! @brief 要素が1つもない場合は true を返します。
Empty()623     bool Empty() const
624     {
625         return m_List.empty();
626     }
627 
628     //! @brief 先頭の要素を参照します。
Peek()629     ElementType& Peek()
630     {
631         return m_List.front();
632     }
633 
634     //! @brief 先頭の要素を参照します。
Peek()635     const ElementType& Peek() const
636     {
637         return m_List.front();
638     }
639 
640     //! @brief 先頭のイテレータを取得します。
Begin()641     iterator Begin()
642     {
643         return m_List.begin();
644     }
645 
646     //! @brief 先頭のイテレータを取得します。
Begin()647     const_iterator Begin() const
648     {
649         return m_List.begin();
650     }
651 
652     //! @brief 末尾のイテレータを取得します。
End()653     iterator End()
654     {
655         return m_List.end();
656     }
657 
658     //! @brief 末尾のイテレータを取得します。
End()659     const_iterator End() const
660     {
661         return m_List.end();
662     }
663 
664     //! @brief 先頭のリバースイテレータを取得します。
ReverseBegin()665     reverse_iterator ReverseBegin()
666     {
667         return m_List.rbegin();
668     }
669 
670     //! @brief 先頭のリバースイテレータを取得します。
ReverseBegin()671     const_reverse_iterator ReverseBegin() const
672     {
673         return m_List.rbegin();
674     }
675 
676     //! @brief 末尾のリバースイテレータを取得します。
ReverseEnd()677     reverse_iterator ReverseEnd()
678     {
679         return m_List.rend();
680     }
681 
682     //! @brief 末尾のリバースイテレータを取得します。
ReverseEnd()683     const_reverse_iterator ReverseEnd() const
684     {
685         return m_List.rend();
686     }
687 
688     //@}
689 
690     //----------------------------------------
691     //! @name ユーティリティ
692     //@{
693 
694     //! @brief クリップ座標系での深度を計算します。(非推奨)
695     //!
696     //! 廃止予定なので、SceneHelper::CalculateDepth をご利用ください。
697     //!
698     //! @sa SceneHelper::CalculateDepth
699     //!
NW_DEPRECATED_FUNCTION(float CalculateDepth (const math::VEC3 & localPosition,const math::MTX34 & worldMatrix,const Camera & camera))700     NW_DEPRECATED_FUNCTION(float CalculateDepth(
701         const math::VEC3& localPosition,
702         const math::MTX34& worldMatrix,
703         const Camera& camera))
704     {
705         return SceneHelper::CalculateDepth(localPosition, worldMatrix, camera);
706     }
707 
708     //! @brief クリップ座標系での深度を計算します。(非推奨)
709     //!
710     //! 廃止予定なので、SceneHelper::CalculateDepth をご利用ください。
711     //!
712     //! @sa SceneHelper::CalculateDepth
713     //!
NW_DEPRECATED_FUNCTION(float CalculateDepth (const math::MTX34 & worldMatrix,const Camera & camera))714     NW_DEPRECATED_FUNCTION(float CalculateDepth(
715         const math::MTX34& worldMatrix,
716         const Camera& camera))
717     {
718         return SceneHelper::CalculateDepth(worldMatrix, camera);
719     }
720 
721     //@}
722 
723 private:
BasicRenderQueue(os::IAllocator * allocator)724     explicit BasicRenderQueue(os::IAllocator* allocator)
725     : GfxObject(allocator),
726       m_List(allocator),
727       m_OpacityKeyFactory(NULL),
728       m_TranslucentKeyFactory(NULL),
729       m_AdditiveKeyFactory(NULL),
730       m_SubtractionKeyFactory(NULL),
731       m_KeyCachingState(UNUSE_CACHED_KEY) {}
732 
BasicRenderQueue(os::IAllocator * allocator,int maxRenderElements)733     BasicRenderQueue(os::IAllocator* allocator, int maxRenderElements)
734     : GfxObject(allocator),
735       m_List(maxRenderElements, allocator),
736       m_OpacityKeyFactory(NULL),
737       m_TranslucentKeyFactory(NULL),
738       m_AdditiveKeyFactory(NULL),
739       m_SubtractionKeyFactory(NULL),
740       m_KeyCachingState(UNUSE_CACHED_KEY) {}
741 
~BasicRenderQueue()742     virtual ~BasicRenderQueue() {}
743 
GetKeyFactory(ResMaterial::TranslucencyKind translucencyKind)744     ElementKeyFactoryType* GetKeyFactory(ResMaterial::TranslucencyKind translucencyKind)
745     {
746         ElementKeyFactoryType* keyFactory = NULL;
747         switch (translucencyKind)
748         {
749         case ResMaterial::TRANSLUCENCY_KIND_LAYER0:
750             keyFactory = this->m_OpacityKeyFactory;
751             break;
752         case ResMaterial::TRANSLUCENCY_KIND_LAYER1:
753             keyFactory = this->m_TranslucentKeyFactory;
754             break;
755         case ResMaterial::TRANSLUCENCY_KIND_LAYER2:
756             keyFactory = this->m_SubtractionKeyFactory;
757             break;
758         case ResMaterial::TRANSLUCENCY_KIND_LAYER3:
759             keyFactory = this->m_AdditiveKeyFactory;
760             break;
761         default: NW_FAILSAFE_IF(false) { keyFactory = this->m_OpacityKeyFactory; } break;
762         }
763         NW_NULL_ASSERT(keyFactory);
764         return keyFactory;
765     }
766 
767     TElementList m_List;
768     ElementKeyFactoryType* m_OpacityKeyFactory;
769     ElementKeyFactoryType* m_TranslucentKeyFactory;
770     ElementKeyFactoryType* m_AdditiveKeyFactory;
771     ElementKeyFactoryType* m_SubtractionKeyFactory;
772 
773     enum KeyCachingState
774     {
775         UNUSE_CACHED_KEY,
776         USE_CACHED_KEY
777     };
778 
779     KeyCachingState m_KeyCachingState;
780 };
781 
782 //! @brief 標準のレンダーキューの定義です。
783 typedef BasicRenderQueue<
784     BasicRenderElement<RenderKeyType>,
785     ut::MoveArray<BasicRenderElement<RenderKeyType> > >
786         RenderQueue;
787 
788 //---------------------------------------------------------------------------
789 //! @brief        ソート比較用関数オブジェクトです。
790 //---------------------------------------------------------------------------
791 struct RenderElementCompare
792 : public std::binary_function<RenderElement, RenderElement, bool>
793 {
operatorRenderElementCompare794     bool operator() (
795         const RenderElement& lhs,
796         const RenderElement& rhs)
797     {
798         return lhs.Key() < rhs.Key();
799     }
800 };
801 
802 } // namespace gfx
803 } // namespace nw
804 
805 #endif // NW_GFX_RENDERQUEUE_H_
806