1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     gfx_SceneUpdater.cpp
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: 27617 $
14  *---------------------------------------------------------------------------*/
15 
16 #include "precompiled.h"
17 
18 #include <nw/gfx/gfx_SceneUpdater.h>
19 
20 #include <nw/gfx/gfx_SceneUpdateHelper.h>
21 #include <nw/gfx/gfx_SceneContext.h>
22 #include <nw/gfx/gfx_SkeletalModel.h>
23 #include <nw/gfx/gfx_ParticleModel.h>
24 #include <nw/gfx/gfx_ParticleSet.h>
25 #include <nw/gfx/res/gfx_ResShape.h>
26 
27 #include <nw/dev.h>
28 
29 namespace nw
30 {
31 namespace gfx
32 {
33 
34 NW_UT_RUNTIME_TYPEINFO_DEFINITION(SceneUpdater, ISceneUpdater);
35 
36 //----------------------------------------
37 SceneUpdater*
Create(os::IAllocator * allocator)38 SceneUpdater::Builder::Create(os::IAllocator* allocator)
39 {
40     NW_NULL_ASSERT(allocator);
41 
42     if (!this->m_SkeletonUpdater)
43     {
44         this->m_SkeletonUpdater.Reset(SkeletonUpdater::Builder()
45             .Create(allocator));
46     }
47 
48     if (!this->m_WorldMatrixUpdater)
49     {
50         this->m_WorldMatrixUpdater.Reset(WorldMatrixUpdater::Builder()
51             .Create(allocator));
52     }
53 
54     if (!this->m_BillboardUpdater)
55     {
56         this->m_BillboardUpdater.Reset(BillboardUpdater::Create(allocator));
57     }
58 
59     void* memory = allocator->Alloc(sizeof(SceneUpdater));
60     NW_NULL_ASSERT(memory);
61 
62     return new(memory) SceneUpdater(
63         allocator,
64         this->m_SkeletonUpdater,
65         this->m_WorldMatrixUpdater,
66         this->m_BillboardUpdater);
67 }
68 
69 //----------------------------------------
70 void
UpdateAll(SceneContext * sceneContext)71 SceneUpdater::UpdateAll(SceneContext* sceneContext)
72 {
73     NW_NULL_ASSERT(sceneContext);
74 
75     this->EvaluateAnim(sceneContext, anim::ResGraphicsAnimGroup::EVALUATION_BEFORE_WORLD_UPDATE);
76     this->UpdateTransformNode(sceneContext);
77     // TODO: 将来、描画カリングを行う場合はここで処理する
78     this->EvaluateAnim(sceneContext, anim::ResGraphicsAnimGroup::EVALUATION_AFTER_SCENE_CULLING);
79     this->UpdateSkeletalModel(sceneContext);
80     this->UpdateAnim(sceneContext);
81 }
82 
83 //----------------------------------------
84 void
SubmitView(RenderQueue * renderQueue,SceneContext * sceneContext,const Camera & camera,u8 layerId,RenderSortMode renderSortMode)85 SceneUpdater::SubmitView(
86     RenderQueue* renderQueue,
87     SceneContext* sceneContext,
88     const Camera& camera,
89     u8 layerId,
90     RenderSortMode renderSortMode)
91 {
92     Model::IsVisibleModelDefaultFunctor isVisibleModel;
93 
94     SceneUpdateHelper::SubmitView(
95         this->m_SkeletonUpdater.Get(),
96         this->m_BillboardUpdater.Get(),
97         renderQueue,
98         sceneContext,
99         camera,
100         layerId,
101         layerId,
102         renderSortMode,
103         this->m_DepthSortMode,
104         &isVisibleModel);
105 }
106 
107 //----------------------------------------
108 void
SubmitView(RenderQueue * renderQueue,SceneContext * sceneContext,const Camera & camera,u8 layerId,u8 particleLayerId,RenderSortMode renderSortMode)109 SceneUpdater::SubmitView(
110     RenderQueue* renderQueue,
111     SceneContext* sceneContext,
112     const Camera& camera,
113     u8 layerId,
114     u8 particleLayerId,
115     RenderSortMode renderSortMode)
116 {
117     Model::IsVisibleModelDefaultFunctor isVisibleModel;
118 
119     SceneUpdateHelper::SubmitView(
120         this->m_SkeletonUpdater.Get(),
121         this->m_BillboardUpdater.Get(),
122         renderQueue,
123         sceneContext,
124         camera,
125         layerId,
126         particleLayerId,
127         renderSortMode,
128         this->m_DepthSortMode,
129         &isVisibleModel);
130 }
131 
132 //----------------------------------------
133 void
SubmitView(RenderQueue * renderQueue,SceneContext * sceneContext,const Camera & camera,u8 layerId,u8 particleLayerId,SceneUpdater::IsVisibleModelFunctor * isVisibleModel,RenderSortMode renderSortMode)134 SceneUpdater::SubmitView(
135     RenderQueue* renderQueue,
136     SceneContext* sceneContext,
137     const Camera& camera,
138     u8 layerId,
139     u8 particleLayerId,
140     SceneUpdater::IsVisibleModelFunctor* isVisibleModel,
141     RenderSortMode renderSortMode)
142 {
143     SceneUpdateHelper::SubmitView(
144         this->m_SkeletonUpdater.Get(),
145         this->m_BillboardUpdater.Get(),
146         renderQueue,
147         sceneContext,
148         camera,
149         layerId,
150         particleLayerId,
151         renderSortMode,
152         this->m_DepthSortMode,
153         isVisibleModel);
154 }
155 
156 //----------------------------------------
157 void
UpdateTransformNode(SceneContext * sceneContext) const158 SceneUpdater::UpdateTransformNode(SceneContext* sceneContext) const
159 {
160     NW_NULL_ASSERT(sceneContext);
161 
162     SceneNodeArray::iterator end = sceneContext->GetSceneNodesEnd();
163     for (SceneNodeArray::iterator node = sceneContext->GetSceneNodesBegin(); node != end; ++node)
164     {
165         (*node)->PreUpdateSignal()(*node, sceneContext);
166 
167         // 親ノードからフラグを継承します。
168         (*node)->InheritTraversalResults();
169 
170         (*node)->UpdateTransform(this->m_WorldMatrixUpdater.Get(), sceneContext);
171     }
172 }
173 
174 //----------------------------------------
175 void
UpdateSkeletalModel(SceneContext * sceneContext) const176 SceneUpdater::UpdateSkeletalModel(SceneContext* sceneContext) const
177 {
178     NW_NULL_ASSERT(sceneContext);
179 
180     SkeletalModelArray::iterator end = sceneContext->GetSkeletalModelsEnd();
181     for (SkeletalModelArray::iterator model = sceneContext->GetSkeletalModelsBegin(); model != end; ++model)
182     {
183         // フルベイクアニメを使用する場合は処理をスキップする。
184         if ((*model)->GetFullBakedAnimEnabled()) { continue; }
185 
186         Skeleton* skeleton = (*model)->GetSkeleton();
187 
188         // スケルトンが既に更新済みの場合は処理をスキップする。
189         if (skeleton->IsUpdated()) { continue; }
190 
191         this->m_SkeletonUpdater->UpdateWorld(
192             skeleton,
193             *(this->m_WorldMatrixUpdater.Get()));
194 
195         skeleton->SetUpdated(true);
196     }
197 }
198 
199 //----------------------------------------
200 void
UpdateAnim(SceneContext * sceneContext) const201 SceneUpdater::UpdateAnim(SceneContext* sceneContext) const
202 {
203     NW_NULL_ASSERT(sceneContext);
204 
205     std::for_each(
206         sceneContext->GetAnimatableNodesBegin(),
207         sceneContext->GetAnimatableNodesEnd(),
208         std::mem_fun(&SceneNode::UpdateFrame));
209 }
210 
211 //----------------------------------------
212 void
EvaluateAnim(SceneContext * sceneContext,anim::ResGraphicsAnimGroup::EvaluationTiming timing) const213 SceneUpdater::EvaluateAnim(SceneContext* sceneContext, anim::ResGraphicsAnimGroup::EvaluationTiming timing) const
214 {
215     NW_NULL_ASSERT(sceneContext);
216 
217     AnimatableNodeArray::iterator animatableNodesEnd = sceneContext->GetAnimatableNodesEnd();
218     for (AnimatableNodeArray::iterator animNode = sceneContext->GetAnimatableNodesBegin();
219         animNode != animatableNodesEnd; ++animNode)
220     {
221         // SceneContext::AnimNodesに格納されたノードは、AnimBindingを持っている
222         (*animNode)->GetAnimBinding()->Evaluate(timing);
223     }
224 }
225 
226 
227 
228 } // namespace gfx
229 } // namespace nw
230