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