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