1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     gfx_SceneBuilder.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: $
16  *---------------------------------------------------------------------------*/
17 
18 #include "precompiled.h"
19 
20 #include <nw/gfx/gfx_SceneBuilder.h>
21 
22 #include <nw/gfx/gfx_SceneNode.h>
23 #include <nw/gfx/gfx_TransformNode.h>
24 #include <nw/gfx/gfx_Model.h>
25 #include <nw/gfx/gfx_SkeletalModel.h>
26 #include <nw/gfx/gfx_ParticleModel.h>
27 #include <nw/gfx/gfx_ParticleEmitter.h>
28 #include <nw/gfx/gfx_ParticleSet.h>
29 #include <nw/gfx/gfx_FragmentLight.h>
30 #include <nw/gfx/gfx_VertexLight.h>
31 #include <nw/gfx/gfx_AmbientLight.h>
32 #include <nw/gfx/gfx_HemiSphereLight.h>
33 #include <nw/gfx/gfx_Fog.h>
34 #include <nw/gfx/gfx_Camera.h>
35 
36 #include <nw/ut/ut_ResUtil.h>
37 #include <nw/ut/ut_ResDictionary.h>
38 
39 namespace nw {
40 namespace gfx {
41 
42 //----------------------------------------
43 SceneObject*
CreateObject(os::IAllocator * allocator,os::IAllocator * deviceAllocator)44 SceneBuilder::CreateObject(
45     os::IAllocator* allocator,
46     os::IAllocator* deviceAllocator
47 )
48 {
49     NW_NULL_ASSERT(allocator);
50     NW_ASSERT(m_Resource.IsValid());
51 
52     // 子階層はたどらずに、このリソースのみを生成します。
53     SceneObject* root = BuildSceneObject(NULL, NULL, 0, m_Resource, allocator, deviceAllocator, false, false);
54 
55     return root;
56 }
57 
58 //----------------------------------------
59 SceneObject*
CreateTree(os::IAllocator * allocator,os::IAllocator * deviceAllocator)60 SceneBuilder::CreateTree(
61     os::IAllocator* allocator,
62     os::IAllocator* deviceAllocator
63 )
64 {
65     NW_NULL_ASSERT(allocator);
66     NW_ASSERT(m_Resource.IsValid());
67 
68     // 子階層を辿って生成します。
69     SceneObject* root = BuildSceneObject(NULL, NULL, 0, m_Resource, allocator, deviceAllocator, true, false);
70 
71     return root;
72 }
73 
74 //----------------------------------------
75 SceneObject*
BuildSceneObject(os::MemorySizeCalculator * pSize,os::MemorySizeCalculator * pDeviceSize,SceneNode * parent,ResSceneObject resource,os::IAllocator * allocator,os::IAllocator * deviceAllocator,bool isRecursive,bool isCalculation) const76 SceneBuilder::BuildSceneObject(
77     os::MemorySizeCalculator* pSize,
78     os::MemorySizeCalculator* pDeviceSize,
79     SceneNode* parent,
80     ResSceneObject resource,
81     os::IAllocator* allocator,
82     os::IAllocator* deviceAllocator,
83     bool isRecursive,
84     bool isCalculation
85 ) const
86 {
87     NW_ASSERT( allocator != NULL || isCalculation );
88 
89     if (!resource.IsValid()) { return 0; }
90 
91     SceneObject* object = 0;
92 
93     switch (resource.GetTypeInfo())
94     {
95     case ResSceneNode::TYPE_INFO:
96         {
97             SceneNode::Description description;
98             description.isFixedSizeMemory = m_IsFixedSizeMemory;
99             description.maxCallbacks = m_MaxCallbacks;
100             description.maxChildren = m_MaxChildren;
101             description.maxAnimObjectsPerGroup = m_MaxAnimObjectsPerGroup;
102             description.isAnimationEnabled = m_IsAnimationEnabled;
103 
104             if (isCalculation)
105             {
106                 if (pSize)
107                 {
108                     SceneNode::GetMemorySizeInternal(pSize, ResStaticCast<ResSceneNode>(resource), description);
109                 }
110                 if (pDeviceSize)
111                 {
112                     SceneNode::GetDeviceMemorySizeInternal(pDeviceSize, ResStaticCast<ResSceneNode>(resource), description);
113                 }
114             }
115             else
116             {
117                 SceneNode* node = SceneNode::Create(
118                     parent, resource, description, allocator);
119                 object = node;
120             }
121         }
122         break;
123 
124     case ResTransformNode::TYPE_INFO:
125         {
126             TransformNode::Description description;
127             description.isFixedSizeMemory = m_IsFixedSizeMemory;
128             description.maxCallbacks = m_MaxCallbacks;
129             description.maxChildren = m_MaxChildren;
130             description.maxAnimObjectsPerGroup = m_MaxAnimObjectsPerGroup;
131             description.isAnimationEnabled = m_IsAnimationEnabled;
132 
133             if (isCalculation)
134             {
135                 if (pSize)
136                 {
137                     TransformNode::GetMemorySizeInternal(pSize, ResStaticCast<ResTransformNode>(resource), description);
138                 }
139                 if (pDeviceSize)
140                 {
141                     TransformNode::GetDeviceMemorySizeInternal(pDeviceSize, ResStaticCast<ResTransformNode>(resource), description);
142                 }
143             }
144             else
145             {
146                 TransformNode* node = TransformNode::Create(
147                     parent,
148                     resource,
149                     description,
150                     allocator);
151                 object = node;
152             }
153         }
154         break;
155 
156     case ResModel::TYPE_INFO:
157         {
158             Model::Description description;
159             description.isFixedSizeMemory = m_IsFixedSizeMemory;
160             description.maxCallbacks = m_MaxCallbacks;
161             description.maxChildren = m_MaxChildren;
162             description.bufferOption = m_BufferOption;
163             description.sharedMaterialModel = m_SharedMaterialModel;
164             description.isAnimationEnabled = m_IsAnimationEnabled;
165 
166             description.maxAnimObjectsPerGroup = m_MaxAnimObjectsPerGroup;
167 
168             if (isCalculation)
169             {
170                 if (pSize)
171                 {
172                     Model::GetMemorySizeInternal(pSize, ResStaticCast<ResModel>(resource), description);
173                 }
174                 if (pDeviceSize)
175                 {
176                     Model::GetDeviceMemorySizeInternal(pDeviceSize, ResStaticCast<ResModel>(resource), description);
177                 }
178             }
179             else
180             {
181                 Model* node = Model::Create(
182                     parent,
183                     resource,
184                     description,
185                     allocator);
186                 object = node;
187             }
188         }
189         break;
190 
191     case ResSkeletalModel::TYPE_INFO:
192         {
193             SkeletalModel::Builder builder;
194             builder
195                 .IsFixedSizeMemory(m_IsFixedSizeMemory)
196                 .MaxCallbacks(m_MaxCallbacks)
197                 .MaxChildren(m_MaxChildren)
198                 .BufferOption(m_BufferOption)
199                 .SharedMaterialModel(m_SharedMaterialModel)
200                 .MaxAnimObjectsPerGroup(m_MaxAnimObjectsPerGroup)
201                 .IsAnimationEnabled(m_IsAnimationEnabled);
202             if (isCalculation)
203             {
204                 if (pSize)
205                 {
206                     builder.GetMemorySizeInternal(pSize, ResStaticCast<ResSkeletalModel>(resource));
207                 }
208                 if (pDeviceSize)
209                 {
210                     builder.GetDeviceMemorySizeInternal(pDeviceSize, ResStaticCast<ResSkeletalModel>(resource));
211                 }
212             }
213             else
214             {
215                 SkeletalModel* node = builder.Create(parent, resource, allocator);
216                 object = node;
217             }
218         }
219         break;
220 
221     case ResParticleModel::TYPE_INFO:
222         {
223             ResParticleModel resNode = ResDynamicCast<ResParticleModel>(resource);
224             NW_ASSERT(resNode.IsValid());
225 
226             ParticleModel::Description description;
227             description.isFixedSizeMemory = m_IsFixedSizeMemory;
228             description.maxCallbacks = m_MaxCallbacks;
229             description.bufferOption = m_BufferOption;
230             description.sharedMaterialModel = m_SharedMaterialModel;
231             description.maxChildren = resNode.GetChildrenCount() +
232                                       resNode.GetParticleSetsCount() +
233                                       m_ParticleSetMarginCount;
234             description.particleSetCount = resNode.GetParticleSetsCount() +
235                                            m_ParticleSetMarginCount;
236             description.isAnimationEnabled = m_IsAnimationEnabled;
237 
238             if (isCalculation)
239             {
240                 if (pSize)
241                 {
242                     ParticleModel::GetMemorySizeInternal(pSize, resNode, description);
243                 }
244                 if (pDeviceSize)
245                 {
246                     ParticleModel::GetDeviceMemorySizeInternal(pDeviceSize, resNode, description);
247                 }
248             }
249             else
250             {
251                 ParticleModel* node = ParticleModel::Create(
252                     parent,
253                     resource,
254                     description,
255                     allocator,
256                     deviceAllocator);
257                 object = node;
258             }
259         }
260         break;
261 
262     case ResParticleEmitter::TYPE_INFO:
263         {
264             ParticleEmitter::Description description;
265             description.isFixedSizeMemory = m_IsFixedSizeMemory;
266             description.maxCallbacks = m_MaxCallbacks;
267             description.maxChildren = m_MaxChildren;
268             description.isAnimationEnabled = m_IsAnimationEnabled;
269 
270             if (isCalculation)
271             {
272                 if (pSize)
273                 {
274                     ParticleEmitter::GetMemorySizeInternal(pSize, ResStaticCast<ResParticleEmitter>(resource), description);
275                 }
276                 if (pDeviceSize)
277                 {
278                     ParticleEmitter::GetDeviceMemorySizeInternal(pDeviceSize, ResStaticCast<ResParticleEmitter>(resource), description);
279                 }
280             }
281             else
282             {
283                 ParticleEmitter* node = ParticleEmitter::Create(
284                     parent,
285                     resource,
286                     description,
287                     allocator);
288                 object = node;
289             }
290         }
291         break;
292 
293     case ResFragmentLight::TYPE_INFO:
294         {
295             FragmentLight::Description description;
296             description.isFixedSizeMemory = m_IsFixedSizeMemory;
297             description.maxCallbacks = m_MaxCallbacks;
298             description.maxChildren = m_MaxChildren;
299             description.maxAnimObjectsPerGroup = m_MaxAnimObjectsPerGroup;
300             description.isAnimationEnabled = m_IsAnimationEnabled;
301 
302             if (isCalculation)
303             {
304                 if (pSize)
305                 {
306                     FragmentLight::GetMemorySizeInternal(pSize, ResStaticCast<ResFragmentLight>(resource), description);
307                 }
308                 if (pDeviceSize)
309                 {
310                     FragmentLight::GetDeviceMemorySizeInternal(pDeviceSize, ResStaticCast<ResFragmentLight>(resource), description);
311                 }
312             }
313             else
314             {
315                 FragmentLight* node = FragmentLight::Create(
316                     parent,
317                     resource,
318                     description,
319                     allocator);
320                 object = node;
321             }
322         }
323         break;
324 
325 #if defined(NW_GFX_VERTEX_LIGHT_ENABLED)
326     case ResVertexLight::TYPE_INFO:
327         {
328             VertexLight::Description description;
329             description.isFixedSizeMemory = m_IsFixedSizeMemory;
330             description.maxCallbacks = m_MaxCallbacks;
331             description.maxChildren = m_MaxChildren;
332             description.maxAnimObjectsPerGroup = m_MaxAnimObjectsPerGroup;
333             description.isAnimationEnabled = m_IsAnimationEnabled;
334 
335             if (isCalculation)
336             {
337                 if (pSize)
338                 {
339                     VertexLight::GetMemorySizeInternal(pSize, ResStaticCast<ResVertexLight>(resource), description);
340                 }
341                 if (pDeviceSize)
342                 {
343                     VertexLight::GetDeviceMemorySizeInternal(pDeviceSize, ResStaticCast<ResVertexLight>(resource), description);
344                 }
345             }
346             else
347             {
348                 VertexLight* node = VertexLight::Create(
349                     parent,
350                     resource,
351                     description,
352                     allocator);
353                 object = node;
354             }
355         }
356         break;
357 #endif
358     case ResAmbientLight::TYPE_INFO:
359         {
360             AmbientLight::Description description;
361             description.isFixedSizeMemory = m_IsFixedSizeMemory;
362             description.maxCallbacks = m_MaxCallbacks;
363             description.maxChildren = m_MaxChildren;
364             description.maxAnimObjectsPerGroup = m_MaxAnimObjectsPerGroup;
365             description.isAnimationEnabled = m_IsAnimationEnabled;
366 
367             if (isCalculation)
368             {
369                 if (pSize)
370                 {
371                     AmbientLight::GetMemorySizeInternal(pSize, ResStaticCast<ResAmbientLight>(resource), description);
372                 }
373                 if (pDeviceSize)
374                 {
375                     AmbientLight::GetDeviceMemorySizeInternal(pDeviceSize, ResStaticCast<ResAmbientLight>(resource), description);
376                 }
377             }
378             else
379             {
380                 AmbientLight* node = AmbientLight::Create(
381                     parent,
382                     resource,
383                     description,
384                     allocator);
385                 object = node;
386             }
387         }
388         break;
389 
390     case ResHemiSphereLight::TYPE_INFO:
391         {
392             HemiSphereLight::Description description;
393             description.isFixedSizeMemory = m_IsFixedSizeMemory;
394             description.maxCallbacks = m_MaxCallbacks;
395             description.maxChildren = m_MaxChildren;
396             description.maxAnimObjectsPerGroup = m_MaxAnimObjectsPerGroup;
397             description.isAnimationEnabled = m_IsAnimationEnabled;
398 
399             if (isCalculation)
400             {
401                 if (pSize)
402                 {
403                     HemiSphereLight::GetMemorySizeInternal(pSize, ResStaticCast<ResHemiSphereLight>(resource), description);
404                 }
405                 if (pDeviceSize)
406                 {
407                     HemiSphereLight::GetDeviceMemorySizeInternal(pDeviceSize, ResStaticCast<ResHemiSphereLight>(resource), description);
408                 }
409             }
410             else
411             {
412                 HemiSphereLight* node = HemiSphereLight::Create(
413                     parent,
414                     resource,
415                     description,
416                     allocator);
417                 object = node;
418             }
419         }
420         break;
421 
422     case ResFog::TYPE_INFO:
423         {
424             Fog::Description description;
425             description.isFixedSizeMemory = m_IsFixedSizeMemory;
426             description.maxCallbacks = m_MaxCallbacks;
427             description.maxChildren = m_MaxChildren;
428             description.isAnimationEnabled = m_IsAnimationEnabled;
429 
430             if (isCalculation)
431             {
432                 if (pSize)
433                 {
434                     Fog::GetMemorySizeInternal(pSize, ResStaticCast<ResFog>(resource), description);
435                 }
436                 if (pDeviceSize)
437                 {
438                     Fog::GetDeviceMemorySizeInternal(pDeviceSize, ResStaticCast<ResFog>(resource), description);
439                 }
440             }
441             else
442             {
443                 Fog* node = Fog::Create(
444                     parent,
445                     resource,
446                     description,
447                     allocator);
448                 object = node;
449             }
450         }
451         break;
452 
453     case ResCamera::TYPE_INFO:
454         {
455             Camera::Description description;
456             description.isFixedSizeMemory = m_IsFixedSizeMemory;
457             description.maxCallbacks = m_MaxCallbacks;
458             description.maxChildren = m_MaxChildren;
459             description.maxAnimObjectsPerGroup = m_MaxAnimObjectsPerGroup;
460             description.isAnimationEnabled = m_IsAnimationEnabled;
461 
462             if (isCalculation)
463             {
464                 if (pSize)
465                 {
466                     Camera::GetMemorySizeInternal(pSize, ResStaticCast<ResCamera>(resource), description);
467                 }
468                 if (pDeviceSize)
469                 {
470                     Camera::GetDeviceMemorySizeInternal(pDeviceSize, ResStaticCast<ResCamera>(resource), description);
471                 }
472             }
473             else
474             {
475                 Camera* node = Camera::Create(
476                     parent,
477                     resource,
478                     description,
479                     allocator);
480                 object = node;
481             }
482         }
483         break;
484 
485     case ResSceneEnvironmentSetting::TYPE_INFO:
486         {
487             SceneEnvironmentSetting::Description description;
488 
489             if (isCalculation)
490             {
491                 if (pSize)
492                 {
493                     SceneEnvironmentSetting::GetMemorySizeInternal(pSize, ResStaticCast<ResSceneEnvironmentSetting>(resource), description);
494                 }
495                 if (pDeviceSize)
496                 {
497                     //SceneEnvironmentSetting::GetDeviceMemorySizeInternal(pDeviceSize, ResStaticCast<ResSceneEnvironmentSetting>(resource), description);
498                 }
499             }
500             else
501             {
502                 SceneEnvironmentSetting* node = SceneEnvironmentSetting::Create(
503                     resource,
504                     description,
505                     allocator);
506                 object = node;
507             }
508         }
509         break;
510 
511     default: NW_FATAL_ERROR("Unknown resource type."); break;
512     }
513 
514     if (isCalculation)
515     {
516         // 子階層のメモリサイズを求める
517         if (isRecursive)
518         {
519             BuildChildren(pSize, pDeviceSize, NULL, resource, NULL, NULL, true);
520         }
521     }
522     else
523     {
524         SceneNode* sceneNode = ut::DynamicCast<SceneNode*>(object);
525 
526         // 子階層を初期化するなら、子をたどる
527         if (sceneNode != NULL && isRecursive)
528         {
529             BuildChildren(NULL, NULL, sceneNode, resource, allocator, deviceAllocator, false);
530         }
531     }
532 
533     return object;
534 }
535 
536 //----------------------------------------
537 void
BuildChildren(os::MemorySizeCalculator * pSize,os::MemorySizeCalculator * pDeviceSize,SceneNode * parent,ResSceneObject resource,os::IAllocator * allocator,os::IAllocator * deviceAllocator,bool isCalculation) const538 SceneBuilder::BuildChildren(
539     os::MemorySizeCalculator* pSize,
540     os::MemorySizeCalculator* pDeviceSize,
541     SceneNode* parent,
542     ResSceneObject resource,
543     os::IAllocator* allocator,
544     os::IAllocator* deviceAllocator,
545     bool isCalculation
546 ) const
547 {
548     NW_NULL_ASSERT(allocator);
549 
550     ResSceneNode resNode = ResSceneNode(resource.ptr());
551     if (!resource.IsValid()) { return; }
552 
553     typedef nw::ut::ResArrayClass<ResSceneObject>::type ResSceneObjectArray;
554     for (ResSceneObjectArray::iterator i = resNode.GetChildren().begin();
555          i != resNode.GetChildren().end(); ++i)
556     {
557         if (isCalculation)
558         {
559             BuildSceneObject(pSize, pDeviceSize, NULL, resource, NULL, NULL, true, true);
560         }
561         else
562         {
563             // 子階層をたどるときは、デフォルトで再帰的に生成を行う
564             SceneObject* child = BuildSceneObject(NULL, NULL, parent, *i, allocator, deviceAllocator, true, false);
565         }
566     }
567 }
568 
569 
570 } // namespace gfx
571 } // namespace nw
572