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