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