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