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: 24971 $
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         Skeleton* skeleton = (*model)->GetSkeleton();
184 
185         // スケルトンが既に更新済みの場合は処理をスキップする。
186         if (skeleton->IsUpdated()) { continue; }
187 
188         this->m_SkeletonUpdater->UpdateWorld(
189             skeleton,
190             *(this->m_WorldMatrixUpdater.Get()));
191 
192         skeleton->SetUpdated(true);
193     }
194 }
195 
196 //----------------------------------------
197 void
UpdateAnim(SceneContext * sceneContext) const198 SceneUpdater::UpdateAnim(SceneContext* sceneContext) const
199 {
200     NW_NULL_ASSERT(sceneContext);
201 
202     std::for_each(
203         sceneContext->GetAnimatableNodesBegin(),
204         sceneContext->GetAnimatableNodesEnd(),
205         std::mem_fun(&SceneNode::UpdateFrame));
206 }
207 
208 //----------------------------------------
209 void
EvaluateAnim(SceneContext * sceneContext,anim::ResGraphicsAnimGroup::EvaluationTiming timing) const210 SceneUpdater::EvaluateAnim(SceneContext* sceneContext, anim::ResGraphicsAnimGroup::EvaluationTiming timing) const
211 {
212     NW_NULL_ASSERT(sceneContext);
213 
214     AnimatableNodeArray::iterator animatableNodesEnd = sceneContext->GetAnimatableNodesEnd();
215     for (AnimatableNodeArray::iterator animNode = sceneContext->GetAnimatableNodesBegin();
216         animNode != animatableNodesEnd; ++animNode)
217     {
218         // SceneContext::AnimNodesに格納されたノードは、AnimBindingを持っている
219         (*animNode)->GetAnimBinding()->Evaluate(timing);
220     }
221 }
222 
223 
224 
225 } // namespace gfx
226 } // namespace nw
227