1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     gfx_SceneUpdateHelper.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: $
16  *---------------------------------------------------------------------------*/
17 
18 #ifndef NW_GFX_SCENEUPDATEHELPER_H_
19 #define NW_GFX_SCENEUPDATEHELPER_H_
20 
21 #include <nw/gfx/gfx_SceneContext.h>
22 #include <nw/gfx/gfx_SkeletalModel.h>
23 #include <nw/gfx/gfx_BillboardUpdater.h>
24 #include <nw/gfx/gfx_RenderQueue.h>
25 
26 namespace nw
27 {
28 namespace gfx
29 {
30 
31 //---------------------------------------------------------------------------
32 //! @brief シーン更新の手助けをするライブラリクラスです。
33 //---------------------------------------------------------------------------
34 class SceneUpdateHelper
35 {
36 public:
37     //---------------------------------------------------------------------------
38     //! @brief カメラの視界に基づいてシーンを更新し、描画キューを構築する関数オブジェクトです。
39     //!
40     //! @tparam EnqueueModelMesh モデルをレンダーキューに積むための関数オブジェクトの型です。
41     //! @tparam EnqueueSkeletalModelFunctor スケルタルモデルをレンダーキューに積むための関数オブジェクトの型です。
42     //! @tparam IsVisibleModel 表示するモデルを識別するための関数オブジェクトの型です。
43     //---------------------------------------------------------------------------
44     template<
45         typename EnqueueModelMesh,
46         typename EnqueueSkeletalModelMesh,
47         typename IsVisibleModel>
48     class SubmitViewFunctor : public std::unary_function<Model*, void>
49     {
50     public:
51         //! @brief        コンストラクタです。
52         //!
53         //! @param[in]    skeletonUpdater
54         //! @param[in]    billboardUpdater
55         //! @param[in]    renderQueue 描画対象となる要素を集めたキューです。
56         //! @param[in]    camera カメラです。
57         //! @param[in]    layerId 描画要素のソート時に最優先に区分される ID です。レイヤーやビューポートの描画を制御するのに用います。
58         //! @param[in]    particleLayerId パーティクル描画用の layerId です。
59         //! @param[in]    isVisibleModel 表示するモデルを識別するための関数オブジェクトです。
60         //!
SubmitViewFunctor(SkeletonUpdater * skeletonUpdater,BillboardUpdater * billboardUpdater,RenderQueue * renderQueue,const Camera * camera,u8 layerId,u8 particleLayerId,IsVisibleModel * isVisibleModel)61         SubmitViewFunctor(
62             SkeletonUpdater* skeletonUpdater,
63             BillboardUpdater* billboardUpdater,
64             RenderQueue* renderQueue,
65             const Camera* camera,
66             u8 layerId,
67             u8 particleLayerId,
68             IsVisibleModel* isVisibleModel)
69         : m_SkeletonUpdater(skeletonUpdater),
70           m_BillboardUpdater(billboardUpdater),
71           m_RenderQueue(renderQueue),
72           m_Camera(camera),
73           m_LayerId(layerId),
74           m_ParticleLayerId(particleLayerId),
75           m_IsVisibleModel(isVisibleModel) {}
76 
77         //! @brief        カメラの視界に基づいてシーンを更新し、描画キューを構築します。
78         //!
79         //! @param[in]    model 描画対象となるモデルです。
80         //!
operator()81         void operator() (Model* model)
82         {
83             // スケルタルモデルの更新を行います。
84             SkeletalModel* skeletalModel = ut::DynamicCast<SkeletalModel*>(model);
85 
86             if (skeletalModel)
87             {
88                 Skeleton* skeleton = skeletalModel->GetSkeleton();
89                 // 必ず Skeleton の更新フラグを false に設定します。
90                 skeleton->SetUpdated(false);
91             }
92 
93             if (!m_IsVisibleModel->IsVisible(model)) { return; }
94 
95             if (skeletalModel)
96             {
97                 if (!skeletalModel->IsSharingSkeleton())
98                 {
99                     this->m_SkeletonUpdater->UpdateView(
100                         skeletalModel->GetSkeleton(),
101                         *this->m_BillboardUpdater,
102                         *this->m_Camera);
103                 }
104 
105                 const Skeleton* skeleton = skeletalModel->GetSkeleton();
106                 ResSkeleton resSkeleton = skeleton->GetResSkeleton();
107 
108                 bool isModelCoordinate =
109                     ut::CheckFlag(resSkeleton.GetFlags(), ResSkeletonData::FLAG_MODEL_COORDINATE);
110                 model->UpdateModelViewMatrixAndNormalMatrix(this->m_Camera->ViewMatrix(), isModelCoordinate);
111 
112                 u8 meshLayerId = m_LayerId | model->GetLayerId();
113 
114                 // ZSort 用の深度を計算して、レンダーキューにメッシュを積みます。
115                 gfx::ResMeshArray meshs = skeletalModel->GetResMeshes();
116                 std::for_each(
117                     meshs.begin(),
118                     meshs.end(),
119                     EnqueueSkeletalModelMesh(this->m_RenderQueue, skeletalModel, meshLayerId, *this->m_Camera));
120             }
121             else
122             {
123                 model->UpdateModelViewMatrixAndNormalMatrix(this->m_Camera->ViewMatrix(), false);
124 
125                 u8 meshLayerId =
126                     ut::IsTypeOf<ParticleModel>(model)
127                     ? this->m_ParticleLayerId
128                     : this->m_LayerId;
129                 meshLayerId |= model->GetLayerId();
130 
131                 // ZSort 用の深度を計算して、レンダーキューにメッシュを積みます。
132                 gfx::ResMeshArray meshs = model->GetResMeshes();
133                 std::for_each(
134                     meshs.begin(),
135                     meshs.end(),
136                     EnqueueModelMesh(this->m_RenderQueue, model, meshLayerId, *this->m_Camera));
137             }
138         }
139 
140     private:
141         SkeletonUpdater* m_SkeletonUpdater;
142         BillboardUpdater* m_BillboardUpdater;
143         RenderQueue* m_RenderQueue;
144         const Camera* m_Camera;
145         u8 m_LayerId;
146         u8 m_ParticleLayerId;
147         IsVisibleModel* m_IsVisibleModel;
148     };
149 
150     //! @brief        カメラの視界に基づいてシーンを更新し、描画キューを構築します。
151     //!
152     //! @tparam       IsVisibleModelFunctor 表示するモデルを識別するための関数オブジェクトの型です。
153     //! @param[in]    skeletonUpdater スケルトンアップデータです。
154     //! @param[in]    billboardUpdater ビルボードアップデータです。
155     //! @param[in]    renderQueue 描画対象となる要素を集めたキューです。
156     //! @param[in]    sceneContext シーンコンテキストです。
157     //! @param[in]    camera カメラです。
158     //! @param[in]    layerId 描画要素のソート時に最優先に区分される ID です。レイヤーやビューポートの描画を制御するのに用います。
159     //! @param[in]    particleLayerId パーティクル描画用の layerId です。
160     //! @param[in]    isVisibleModel 表示するモデルを識別するための関数オブジェクトです。
161     //! @param[in]    renderSortMode 描画ソートモードです。
162     //!
163     template<typename IsVisibleModelFunctor>
SubmitView(SkeletonUpdater * skeletonUpdater,BillboardUpdater * billboardUpdater,RenderQueue * renderQueue,SceneContext * sceneContext,const Camera & camera,u8 layerId,u8 particleLayerId,ISceneUpdater::RenderSortMode renderSortMode,ISceneUpdater::DepthSortMode depthSortMode,IsVisibleModelFunctor * isVisibleModel)164     static void SubmitView(
165         SkeletonUpdater* skeletonUpdater,
166         BillboardUpdater* billboardUpdater,
167         RenderQueue* renderQueue,
168         SceneContext* sceneContext,
169         const Camera& camera,
170         u8 layerId,
171         u8 particleLayerId,
172         ISceneUpdater::RenderSortMode renderSortMode,
173         ISceneUpdater::DepthSortMode depthSortMode,
174         IsVisibleModelFunctor* isVisibleModel)
175     {
176         NW_NULL_ASSERT(sceneContext);
177 
178         if (depthSortMode == ISceneUpdater::SORT_DEPTH_OF_TRANSLUCENT_MESH)
179         {
180             // 半透明のメッシュのみ深度計算を行います。
181             // 不透明などのメッシュは深度によるソートがされなくなりますが、
182             // 深度計算分のCPUの処理負荷を削減します。
183 
184             typedef SubmitViewFunctor<
185                 RenderQueue::FastEnqueueModelFunctor,
186                 RenderQueue::FastEnqueueSkeletalModelFunctor,
187                 IsVisibleModelFunctor> FastMeshBaseSubmitViewFunctor;
188 
189             typedef SubmitViewFunctor<
190                 RenderQueue::EnqueueModelTranslucentModelBaseFunctor,
191                 RenderQueue::EnqueueSkeletalModelTranslucentModelBaseFunctor,
192                 IsVisibleModelFunctor> FastTranslucentModelBaseSubmitViewFunctor;
193 
194             if (renderSortMode == ISceneUpdater::OPAQUE_MESH_BASE_AND_TRANSLUCENT_MODEL_BASE_SORT)
195             {
196                 std::for_each(
197                     sceneContext->GetModelsBegin(),
198                     sceneContext->GetModelsEnd(),
199                     FastTranslucentModelBaseSubmitViewFunctor(
200                             skeletonUpdater, billboardUpdater,
201                             renderQueue, &camera, layerId, particleLayerId, isVisibleModel));
202             }
203             else
204             {
205                 std::for_each(
206                     sceneContext->GetModelsBegin(),
207                     sceneContext->GetModelsEnd(),
208                     FastMeshBaseSubmitViewFunctor(
209                             skeletonUpdater, billboardUpdater,
210                             renderQueue, &camera, layerId, particleLayerId, isVisibleModel));
211             }
212         }
213         else
214         {
215             // すべてのメッシュの深度計算を行います。
216 
217             typedef SubmitViewFunctor<
218                 RenderQueue::EnqueueModelFunctor,
219                 RenderQueue::EnqueueSkeletalModelFunctor,
220                 IsVisibleModelFunctor> MeshBaseSubmitViewFunctor;
221 
222             typedef SubmitViewFunctor<
223                 RenderQueue::EnqueueModelTranslucentModelBaseFunctor,
224                 RenderQueue::EnqueueSkeletalModelTranslucentModelBaseFunctor,
225                 IsVisibleModelFunctor> TranslucentModelBaseSubmitViewFunctor;
226 
227             if (renderSortMode == ISceneUpdater::OPAQUE_MESH_BASE_AND_TRANSLUCENT_MODEL_BASE_SORT)
228             {
229                 std::for_each(
230                     sceneContext->GetModelsBegin(),
231                     sceneContext->GetModelsEnd(),
232                     TranslucentModelBaseSubmitViewFunctor(
233                             skeletonUpdater, billboardUpdater,
234                             renderQueue, &camera, layerId, particleLayerId, isVisibleModel));
235             }
236             else
237             {
238                 std::for_each(
239                     sceneContext->GetModelsBegin(),
240                     sceneContext->GetModelsEnd(),
241                     MeshBaseSubmitViewFunctor(
242                             skeletonUpdater, billboardUpdater,
243                             renderQueue, &camera, layerId, particleLayerId, isVisibleModel));
244             }
245         }
246     }
247 
248 private:
SceneUpdateHelper()249     SceneUpdateHelper() {}
~SceneUpdateHelper()250     ~SceneUpdateHelper() {}
251 };
252 
253 
254 } // namespace gfx
255 } // namespace nw
256 
257 #endif // NW_GFX_SCENEUPDATEHELPER_H_
258