1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     gfx_SceneBuilder.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: 13148 $
14  *---------------------------------------------------------------------------*/
15 
16 #include "precompiled.h"
17 
18 #include <nw/gfx/gfx_SceneBuilder.h>
19 
20 #include <nw/gfx/gfx_SceneNode.h>
21 #include <nw/gfx/gfx_TransformNode.h>
22 #include <nw/gfx/gfx_Model.h>
23 #include <nw/gfx/gfx_SkeletalModel.h>
24 #include <nw/gfx/gfx_ParticleModel.h>
25 #include <nw/gfx/gfx_ParticleEmitter.h>
26 #include <nw/gfx/gfx_ParticleSet.h>
27 #include <nw/gfx/gfx_FragmentLight.h>
28 #include <nw/gfx/gfx_VertexLight.h>
29 #include <nw/gfx/gfx_AmbientLight.h>
30 #include <nw/gfx/gfx_HemiSphereLight.h>
31 #include <nw/gfx/gfx_Fog.h>
32 #include <nw/gfx/gfx_Camera.h>
33 
34 #include <nw/ut/ut_ResUtil.h>
35 #include <nw/ut/ut_ResDictionary.h>
36 
37 namespace nw {
38 namespace gfx {
39 
40 //----------------------------------------
41 SceneObject*
CreateObject(os::IAllocator * allocator,os::IAllocator * deviceAllocator)42 SceneBuilder::CreateObject(
43     os::IAllocator* allocator,
44     os::IAllocator* deviceAllocator
45 )
46 {
47     NW_NULL_ASSERT(allocator);
48     NW_ASSERT(m_Resource.IsValid());
49 
50     // 子階層はたどらずに、このリソースのみを生成します。
51     SceneObject* root = BuildSceneObject(0, m_Resource, allocator, deviceAllocator, false);
52 
53     return root;
54 }
55 
56 //----------------------------------------
57 SceneObject*
CreateTree(os::IAllocator * allocator,os::IAllocator * deviceAllocator)58 SceneBuilder::CreateTree(
59     os::IAllocator* allocator,
60     os::IAllocator* deviceAllocator
61 )
62 {
63     NW_NULL_ASSERT(allocator);
64     NW_ASSERT(m_Resource.IsValid());
65 
66     // 子階層を辿って生成します。
67     SceneObject* root = BuildSceneObject(0, m_Resource, allocator, deviceAllocator, true);
68 
69     return root;
70 }
71 
72 //----------------------------------------
73 SceneObject*
BuildSceneObject(SceneNode * parent,ResSceneObject resource,os::IAllocator * allocator,os::IAllocator * deviceAllocator,bool isRecursive)74 SceneBuilder::BuildSceneObject(
75     SceneNode* parent,
76     ResSceneObject resource,
77     os::IAllocator* allocator,
78     os::IAllocator* deviceAllocator,
79     bool isRecursive
80 )
81 {
82     NW_NULL_ASSERT(allocator);
83     if (!resource.IsValid()) { return 0; }
84 
85     SceneObject* object = 0;
86 
87     switch (resource.GetTypeInfo())
88     {
89     case ResSceneNode::TYPE_INFO:
90         {
91             SceneNode::Description description;
92             description.isFixedSizeMemory = m_IsFixedSizeMemory;
93             description.maxCallbacks = m_MaxCallbacks;
94             description.maxChildren = m_MaxChildren;
95             description.maxAnimObjectsPerGroup = m_MaxAnimObjectsPerGroup;
96             description.isAnimationEnabled = m_IsAnimationEnabled;
97 
98             SceneNode* node = SceneNode::Create(
99                 parent, resource, description, allocator);
100             object = node;
101         }
102         break;
103 
104     case ResTransformNode::TYPE_INFO:
105         {
106             TransformNode::Description description;
107             description.isFixedSizeMemory = m_IsFixedSizeMemory;
108             description.maxCallbacks = m_MaxCallbacks;
109             description.maxChildren = m_MaxChildren;
110             description.maxAnimObjectsPerGroup = m_MaxAnimObjectsPerGroup;
111             description.isAnimationEnabled = m_IsAnimationEnabled;
112 
113             TransformNode* node = TransformNode::Create(
114                 parent,
115                 resource,
116                 description,
117                 allocator);
118             object = node;
119         }
120         break;
121 
122     case ResModel::TYPE_INFO:
123         {
124             Model::Description description;
125             description.isFixedSizeMemory = m_IsFixedSizeMemory;
126             description.maxCallbacks = m_MaxCallbacks;
127             description.maxChildren = m_MaxChildren;
128             description.bufferOption = m_BufferOption;
129             description.sharedMaterialModel = m_SharedMaterialModel;
130             description.isAnimationEnabled = m_IsAnimationEnabled;
131 
132             description.maxAnimObjectsPerGroup = m_MaxAnimObjectsPerGroup;
133 
134             Model* node = Model::Create(
135                 parent,
136                 resource,
137                 description,
138                 allocator);
139             object = node;
140         }
141         break;
142 
143     case ResSkeletalModel::TYPE_INFO:
144         {
145             SkeletalModel* node = SkeletalModel::Builder()
146                 .IsFixedSizeMemory(m_IsFixedSizeMemory)
147                 .MaxCallbacks(m_MaxCallbacks)
148                 .MaxChildren(m_MaxChildren)
149                 .BufferOption(m_BufferOption)
150                 .SharedMaterialModel(m_SharedMaterialModel)
151                 .MaxAnimObjectsPerGroup(m_MaxAnimObjectsPerGroup)
152                 .IsAnimationEnabled(m_IsAnimationEnabled)
153                 .Create(parent, resource, allocator);
154             object = node;
155         }
156         break;
157 
158     case ResParticleModel::TYPE_INFO:
159         {
160             ResParticleModel resNode = ResDynamicCast<ResParticleModel>(resource);
161             NW_ASSERT(resNode.IsValid());
162 
163             ParticleModel::Description description;
164             description.isFixedSizeMemory = m_IsFixedSizeMemory;
165             description.maxCallbacks = m_MaxCallbacks;
166             description.bufferOption = m_BufferOption;
167             description.sharedMaterialModel = m_SharedMaterialModel;
168             description.maxChildren = resNode.GetChildrenCount() +
169                                       resNode.GetParticleSetsCount() +
170                                       m_ParticleSetMarginCount;
171             description.particleSetCount = resNode.GetParticleSetsCount() +
172                                            m_ParticleSetMarginCount;
173             description.isAnimationEnabled = m_IsAnimationEnabled;
174 
175             ParticleModel* node = ParticleModel::Create(
176                 parent,
177                 resource,
178                 description,
179                 allocator,
180                 deviceAllocator);
181             object = node;
182         }
183         break;
184 
185     case ResParticleEmitter::TYPE_INFO:
186         {
187             ParticleEmitter::Description description;
188             description.isFixedSizeMemory = m_IsFixedSizeMemory;
189             description.maxCallbacks = m_MaxCallbacks;
190             description.maxChildren = m_MaxChildren;
191             description.isAnimationEnabled = m_IsAnimationEnabled;
192 
193             ParticleEmitter* node = ParticleEmitter::Create(
194                 parent,
195                 resource,
196                 description,
197                 allocator);
198             object = node;
199         }
200         break;
201 
202     case ResFragmentLight::TYPE_INFO:
203         {
204             FragmentLight::Description description;
205             description.isFixedSizeMemory = m_IsFixedSizeMemory;
206             description.maxCallbacks = m_MaxCallbacks;
207             description.maxChildren = m_MaxChildren;
208             description.maxAnimObjectsPerGroup = m_MaxAnimObjectsPerGroup;
209             description.isAnimationEnabled = m_IsAnimationEnabled;
210 
211             FragmentLight* node = FragmentLight::Create(
212                 parent,
213                 resource,
214                 description,
215                 allocator);
216             object = node;
217         }
218         break;
219 
220 #if defined(NW_GFX_VERTEX_LIGHT_ENABLED)
221     case ResVertexLight::TYPE_INFO:
222         {
223             VertexLight::Description description;
224             description.isFixedSizeMemory = m_IsFixedSizeMemory;
225             description.maxCallbacks = m_MaxCallbacks;
226             description.maxChildren = m_MaxChildren;
227             description.maxAnimObjectsPerGroup = m_MaxAnimObjectsPerGroup;
228             description.isAnimationEnabled = m_IsAnimationEnabled;
229 
230             VertexLight* node = VertexLight::Create(
231                 parent,
232                 resource,
233                 description,
234                 allocator);
235             object = node;
236         }
237         break;
238 #endif
239     case ResAmbientLight::TYPE_INFO:
240         {
241             AmbientLight::Description description;
242             description.isFixedSizeMemory = m_IsFixedSizeMemory;
243             description.maxCallbacks = m_MaxCallbacks;
244             description.maxChildren = m_MaxChildren;
245             description.maxAnimObjectsPerGroup = m_MaxAnimObjectsPerGroup;
246             description.isAnimationEnabled = m_IsAnimationEnabled;
247 
248             AmbientLight* node = AmbientLight::Create(
249                 parent,
250                 resource,
251                 description,
252                 allocator);
253             object = node;
254         }
255         break;
256 
257     case ResHemiSphereLight::TYPE_INFO:
258         {
259             HemiSphereLight::Description description;
260             description.isFixedSizeMemory = m_IsFixedSizeMemory;
261             description.maxCallbacks = m_MaxCallbacks;
262             description.maxChildren = m_MaxChildren;
263             description.maxAnimObjectsPerGroup = m_MaxAnimObjectsPerGroup;
264             description.isAnimationEnabled = m_IsAnimationEnabled;
265 
266             HemiSphereLight* node = HemiSphereLight::Create(
267                 parent,
268                 resource,
269                 description,
270                 allocator);
271             object = node;
272         }
273         break;
274 
275     case ResFog::TYPE_INFO:
276         {
277             Fog::Description description;
278             description.isFixedSizeMemory = m_IsFixedSizeMemory;
279             description.maxCallbacks = m_MaxCallbacks;
280             description.maxChildren = m_MaxChildren;
281             description.isAnimationEnabled = m_IsAnimationEnabled;
282 
283             Fog* node = Fog::Create(
284                 parent,
285                 resource,
286                 description,
287                 allocator);
288             object = node;
289         }
290         break;
291 
292     case ResCamera::TYPE_INFO:
293         {
294             Camera::Description description;
295             description.isFixedSizeMemory = m_IsFixedSizeMemory;
296             description.maxCallbacks = m_MaxCallbacks;
297             description.maxChildren = m_MaxChildren;
298             description.maxAnimObjectsPerGroup = m_MaxAnimObjectsPerGroup;
299             description.isAnimationEnabled = m_IsAnimationEnabled;
300 
301             Camera* node = Camera::Create(
302                 parent,
303                 resource,
304                 description,
305                 allocator);
306             object = node;
307         }
308         break;
309 
310     case ResSceneEnvironmentSetting::TYPE_INFO:
311         {
312             SceneEnvironmentSetting::Description description;
313 
314             SceneEnvironmentSetting* node = SceneEnvironmentSetting::Create(
315                 resource,
316                 description,
317                 allocator);
318             object = node;
319         }
320         break;
321 
322     default: NW_FATAL_ERROR("Unknown resource type."); break;
323     }
324 
325     SceneNode* sceneNode = ut::DynamicCast<SceneNode*>(object);
326 
327     // 子階層を初期化するなら、子をたどる
328     if (sceneNode != NULL && isRecursive)
329     {
330         BuildChildren(sceneNode, resource, allocator, deviceAllocator);
331     }
332 
333     return object;
334 }
335 
336 //----------------------------------------
337 void
BuildChildren(SceneNode * parent,ResSceneObject resource,os::IAllocator * allocator,os::IAllocator * deviceAllocator)338 SceneBuilder::BuildChildren(
339     SceneNode* parent,
340     ResSceneObject resource,
341     os::IAllocator* allocator,
342     os::IAllocator* deviceAllocator
343 )
344 {
345     NW_NULL_ASSERT(allocator);
346 
347     ResSceneNode resNode = ResSceneNode(resource.ptr());
348     if (!resource.IsValid()) { return; }
349 
350     typedef nw::ut::ResArrayClass<ResSceneObject>::type ResSceneObjectArray;
351     for (ResSceneObjectArray::iterator i = resNode.GetChildren().begin();
352          i != resNode.GetChildren().end(); ++i)
353     {
354         // 子階層をたどるときは、デフォルトで再帰的に生成を行う
355         SceneObject* child = BuildSceneObject(parent, *i, allocator, deviceAllocator, true);
356     }
357 }
358 
359 
360 } // namespace gfx
361 } // namespace nw
362