1 /*---------------------------------------------------------------------------*
2 Project: NintendoWare
3 File: MultiInstanceDemo.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 #define NW_DEBUG_CHECK_MEMORY_LEAK
19
20 #include <nn/os.h>
21 #include <nn/fs.h>
22
23 #include <nw/types.h>
24
25 #include <nw/demo.h>
26 #include <nw/dev.h>
27 #include <nw/gfx.h>
28 #include <nw/ut.h>
29 #include <nw/anim.h>
30
31 namespace
32 {
33
34 //----------------------------------------
35 // メモリ関係
36
37 // デバイスメモリを確保するためのアロケータです。
38 nw::demo::DemoAllocator s_DeviceAllocator;
39
40 //----------------------------------------
41 // ファイル名の定義です。
42 const wchar_t* SKY_SPHERE_FILE_NAME = NW_DEMO_FILE_PATH(L"SkySphere.bcmdl");
43
44 const wchar_t* MODEL_RESOURCE_FILES[] =
45 {
46 NW_DEMO_FILE_PATH(L"Male.bcmdl"),
47 NW_DEMO_FILE_PATH(L"SceneEnvironmentSetting.bcenv"),
48 NW_DEMO_FILE_PATH(L"FragmentLight.bcenv"),
49 };
50
51 const wchar_t* SKELETAL_ANIM_RESOURCE_FILES[] =
52 {
53 NW_DEMO_FILE_PATH(L"Walk.bcskla"),
54 };
55
56 //----------------------------------------
57 // 描画関係
58 const int RENDER_TARGET_COUNT = 1;
59 typedef nw::ut::FixedSizeArray<nw::gfx::IRenderTarget*, RENDER_TARGET_COUNT> RenderTargetArray;
60
61 RenderTargetArray s_RenderTargets;
62 nw::demo::SceneSystem* s_SceneSystem = NULL;
63 nw::demo::RenderSystem* s_RenderSystem = NULL;
64
65 nw::demo::GraphicsDrawing s_GraphicsDrawing;
66
67 //----------------------------------------
68 // リソース関係
69 nw::demo::ResourceArray s_Resources;
70
71 //----------------------------------------
72 // シーン関係
73 const int SCENE_NODE_COUNT = 4;
74 nw::gfx::SceneNode* s_SceneRoot = NULL;
75 nw::gfx::SceneNode* s_ModelRoot = NULL;
76 s32 s_FrameCount = 0;
77 nw::gfx::Camera* s_BaseCamera = NULL;
78 nw::gfx::Camera* s_LeftCamera = NULL;
79 nw::gfx::Camera* s_RightCamera = NULL;
80 const f32 s_fNearPlane = 0.1f;
81
82 //----------------------------------------
83 // シーン環境関係
84 const s32 ENVIRONMENT_SETTINGS_COUNT = 1;
85
86 typedef nw::ut::FixedSizeArray<nw::gfx::SceneEnvironmentSetting*, ENVIRONMENT_SETTINGS_COUNT> SceneEnvironmentSettingArray;
87 SceneEnvironmentSettingArray s_SceneEnvironmentSettings;
88
89 const s32 s_BaseCameraIndex = 0;
90
91 //----------------------------------------
92 // アニメーション関係
93 float s_AnimWeight0 = 0.5f;
94 float s_AnimWeight1 = 0.5f;
95
96 const int MAX_ANIM_MODELS = 80;
97 struct AnimModelSet {
98 nw::gfx::SkeletalModel* skeletalModel;
99 nw::anim::ResAnim resAnim;
100 nw::gfx::TransformAnimEvaluator* evaluator;
101 bool isSkeletonShared;
102 };
103 typedef nw::ut::FixedSizeArray<AnimModelSet, MAX_ANIM_MODELS> AnimModelSetArray;
104 AnimModelSetArray s_AnimModelSets;
105 AnimModelSet s_AnimModelSetTemplate;
106
107 u32 s_NumCopy = 0;
108 u32 s_NumSkeletonSharedCopy = 0;
109
110 //----------------------------------------
111 // 操作関係
112 s32 s_WhirlDepth;
113 s32 s_WhirlPos;
114 /*!--------------------------------------------------------------------------*
115 @brief モデル複製の方法です。
116 *---------------------------------------------------------------------------*/
117 enum DuplicationMode
118 {
119 DUPLICATION, //!< 新しくスケルタルモデルを生成します。
120 SKELETON_SHARED //!< スケルトンを共有したモデルを生成します。
121 };
122
123 /*!--------------------------------------------------------------------------*
124 @brief グラフィックス関連の初期化を行います。
125 *---------------------------------------------------------------------------*/
126 void
InitializeGraphics()127 InitializeGraphics()
128 {
129 nw::gfx::CommandCacheManager::SetAllocator( &s_DeviceAllocator );
130
131 // renderDescriptionへステレオの設定を行います。
132 nw::demo::RenderSystem::Description renderDescription;
133
134 renderDescription.reusableCommandBufferSize = 0x100000;
135 renderDescription.reusableCommandRequestCount = 512;
136 renderDescription.upperScreenMode = nw::demo::UPPER_SCREEN_MODE_STEREO;
137
138 s_RenderSystem = nw::demo::RenderSystem::Create(&s_DeviceAllocator, renderDescription);
139
140 s_GraphicsDrawing.SetScreenSize(
141 renderDescription.lowerScreenDescription.width,
142 renderDescription.lowerScreenDescription.height
143 );
144
145 nw::demo::Utility::InitializeGraphicsDrawing(&s_DeviceAllocator, s_GraphicsDrawing);
146
147 s_RenderTargets.push_back(
148 nw::demo::Utility::CreateUpperScreenBuffer(&s_DeviceAllocator, renderDescription)
149 );
150 NW_ASSERT(!s_RenderTargets.empty());
151 s_RenderSystem->GetRenderContext()->SetRenderTarget(s_RenderTargets.front());
152
153 nw::demo::SceneSystem::Description sceneDescription;
154 sceneDescription.maxSceneNodes = MAX_ANIM_MODELS + 10;
155 sceneDescription.maxSkeletalModels = MAX_ANIM_MODELS + 1;
156 sceneDescription.maxModels = MAX_ANIM_MODELS + 1;
157 sceneDescription.isFixedSizeMemory = false;
158 s_SceneSystem = nw::demo::SceneSystem::Create(&s_DeviceAllocator, sceneDescription);
159
160 // デモ用の最遠景モデルをレンダリングシステムに設定します。
161 // gfx のデモでは glClear などを用いずに背景で塗りつぶしを行います。
162 s_RenderSystem->LoadSkyModel(SKY_SPHERE_FILE_NAME);
163
164 NW_GL_ASSERT();
165 }
166
167 /*!--------------------------------------------------------------------------*
168 @brief グラフィックス関連の後始末をします。
169 *---------------------------------------------------------------------------*/
170 void
TerminateGraphics()171 TerminateGraphics()
172 {
173 nw::gfx::SafeDestroy(s_LeftCamera);
174
175 nw::gfx::SafeDestroy(s_RightCamera);
176
177 nw::gfx::SafeDestroy(s_SceneSystem);
178
179 nw::gfx::SafeDestroyAll(s_RenderTargets);
180
181 s_GraphicsDrawing.Finalize();
182
183 nw::gfx::SafeDestroy(s_RenderSystem);
184
185 NW_GL_ASSERT();
186 }
187
188 /*!--------------------------------------------------------------------------*
189 @brief ファイルからトランスフォームアニメーション評価を生成します。
190
191 @param[in] maxBones 最大メンバ数です。
192 @param[in] translateAnimEnabled 移動アニメーションが有効かどうかです。
193 @param[in] resAnim トランスフォームアニメーションのリソースです。
194
195 @return トランスフォームアニメーション評価です。
196 *---------------------------------------------------------------------------*/
197 nw::gfx::TransformAnimEvaluator*
CreateTransformAnimEvaluator(const int maxMembers,const bool translateAnimEnabled,nw::anim::ResAnim resAnim)198 CreateTransformAnimEvaluator(
199 const int maxMembers,
200 const bool translateAnimEnabled,
201 nw::anim::ResAnim resAnim
202 )
203 {
204 if (!resAnim.IsValid())
205 {
206 return NULL;
207 }
208
209 //----------------------------------------
210 // トランスフォームアニメーション評価を生成します。
211 //
212 // アニメーションを1つのモデルにのみ適用する場合や、
213 // コマ形式データの場合は、 AllocCache を false にすると処理負荷が下がります。
214 nw::gfx::TransformAnimEvaluator* evaluator = nw::gfx::TransformAnimEvaluator::Builder()
215 .AnimData(resAnim)
216 .MaxMembers(maxMembers)
217 .MaxAnimMembers(resAnim.GetMemberAnimSetCount())
218 .AllocCache(false)
219 .Create(&s_DeviceAllocator);
220
221 // 移動アニメーションの無効化フラグを設定します。
222 evaluator->SetIsTranslateDisabled(!translateAnimEnabled);
223
224 return evaluator;
225 }
226
227 /*!--------------------------------------------------------------------------*
228 @brief スケルタルアニメーションにアニメーション評価をバインドし、そのアニメーション評価を返します。
229 *---------------------------------------------------------------------------*/
230 nw::gfx::TransformAnimEvaluator*
InitializeSkeletalAnim(nw::gfx::SkeletalModel * model,nw::anim::ResAnim resAnim)231 InitializeSkeletalAnim(
232 nw::gfx::SkeletalModel* model,
233 nw::anim::ResAnim resAnim
234 )
235 {
236 nw::gfx::AnimGroup* animGroup = model->GetSkeletalAnimGroup();
237 NW_NULL_ASSERT(animGroup);
238
239 nw::gfx::ResSkeletalModel resModel = model->GetResSkeletalModel();
240 nw::gfx::ResSkeleton resSkeleton = resModel.GetSkeleton();
241 const int maxBones = resSkeleton.GetBonesCount();
242 const bool translateAnimEnabled =
243 nw::ut::CheckFlag(resSkeleton.GetFlags(), nw::gfx::ResSkeletonData::FLAG_TRANSLATE_ANIMATION_ENABLED);
244
245 nw::gfx::TransformAnimEvaluator* evaluator = CreateTransformAnimEvaluator(
246 maxBones, translateAnimEnabled, resAnim);
247
248 NW_NULL_ASSERT(evaluator);
249
250 // アニメーションをバインドします。
251 bool bindResult = evaluator->Bind(animGroup);
252
253 // アニメーションをモデルに登録します。
254 model->SetSkeletalAnimObject(evaluator);
255
256 return evaluator;
257 }
258
259 /*!--------------------------------------------------------------------------*
260 @brief アニメーションの後始末をします。
261 *---------------------------------------------------------------------------*/
262 void
TerminateAnim(void)263 TerminateAnim(void)
264 {
265 for (int animIdx = 0; animIdx < s_AnimModelSets.Size(); ++animIdx)
266 {
267 nw::gfx::SafeDestroy(s_AnimModelSets[animIdx].evaluator);
268 }
269 s_AnimModelSets.clear();
270
271 nw::gfx::SafeDestroy(s_AnimModelSetTemplate.evaluator);
272
273 }
274
275 /*!--------------------------------------------------------------------------*
276 @brief ルートノード関連の構築をします。
277 *---------------------------------------------------------------------------*/
278 void
BuildRootNodes()279 BuildRootNodes()
280 {
281 NW_ASSERT(s_SceneRoot == NULL);
282 s_SceneRoot = nw::gfx::TransformNode::DynamicBuilder()
283 .IsFixedSizeMemory(false)
284 .Create(&s_DeviceAllocator);
285 NW_NULL_ASSERT(s_SceneRoot);
286
287 NW_ASSERT(s_ModelRoot == NULL);
288 s_ModelRoot = nw::gfx::TransformNode::DynamicBuilder()
289 .IsFixedSizeMemory(false)
290 .Create(&s_DeviceAllocator);
291 s_SceneRoot->AttachChild(s_ModelRoot);
292 NW_NULL_ASSERT(s_ModelRoot);
293 }
294
295 /*!--------------------------------------------------------------------------*
296 @brief カメラ関連の構築をします。
297 *---------------------------------------------------------------------------*/
298 void
BuildCameras()299 BuildCameras()
300 {
301 nw::demo::Utility::CreateStereoCameras(
302 &s_BaseCamera,
303 &s_LeftCamera,
304 &s_RightCamera,
305 &s_DeviceAllocator,
306 nw::math::VEC3(50.0f, 40.0f, 50.0f),
307 nw::math::VEC3(0.0f, 10.0f, 0.0f),
308 s_fNearPlane
309 );
310 s_SceneRoot->AttachChild(s_BaseCamera);
311 s_SceneSystem->GetCameraController()->Register(s_BaseCamera);
312 }
313
314 /*!--------------------------------------------------------------------------*
315 @brief リソース関連の構築をします。
316 *---------------------------------------------------------------------------*/
317 void
BuildResources(nw::demo::ResourceSet * resourceSet)318 BuildResources(nw::demo::ResourceSet* resourceSet)
319 {
320 resourceSet->resource.ForeachTexture(nw::gfx::LocationFlagSetter(NN_GX_MEM_VRAMA | GL_NO_COPY_FCRAM_DMP));
321 resourceSet->resource.ForeachIndexStream(nw::gfx::LocationFlagSetter(NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP));
322 resourceSet->resource.ForeachVertexStream(nw::gfx::LocationFlagSetter(NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP));
323
324 nw::gfx::Result result = resourceSet->resource.Setup(&s_DeviceAllocator);
325 if (result.IsFailure())
326 {
327 NW_FATAL_ERROR("Fail to set up model. A result code is 0x%x", result.GetCode());
328 }
329
330 nw::ut::MoveArray<nw::gfx::SceneNode*> sceneNodeArray(&s_DeviceAllocator);
331
332 nw::gfx::ResModelArray models = resourceSet->resource.GetModels();
333 nw::gfx::ResModelArray::iterator modelsEnd = models.end();
334 for (nw::gfx::ResModelArray::iterator modelResource = models.begin();
335 modelResource != modelsEnd; ++modelResource)
336 {
337 nw::gfx::SceneNode* node = nw::demo::Utility::CreateSceneNode(
338 &s_DeviceAllocator,
339 (*modelResource)
340 );
341 NW_NULL_ASSERT(node);
342 sceneNodeArray.push_back(node);
343
344 s_AnimModelSetTemplate.skeletalModel = nw::ut::DynamicCast<nw::gfx::SkeletalModel*>(node);
345 }
346
347 nw::gfx::ResLightArray lights = resourceSet->resource.GetLights();
348 nw::gfx::ResLightArray::iterator lightsEnd = lights.end();
349 for (nw::gfx::ResLightArray::iterator lightResource = lights.begin();
350 lightResource != lightsEnd; ++lightResource)
351 {
352 nw::gfx::SceneNode* node = nw::demo::Utility::CreateSceneNode(
353 &s_DeviceAllocator,
354 (*lightResource)
355 );
356 NW_NULL_ASSERT(node);
357 sceneNodeArray.push_back(node);
358 }
359
360 // 親子付け参照関係を解決
361 nw::gfx::SceneHelper::ResolveReference(sceneNodeArray);
362
363 // モデルをシーンに追加
364 nw::gfx::SceneHelper::ForeachRootNodes(
365 sceneNodeArray.Begin(),
366 sceneNodeArray.End(),
367 nw::gfx::AttachNode(s_ModelRoot)
368 );
369
370 nw::gfx::ResSceneEnvironmentSettingArray settings = resourceSet->resource.GetSceneEnvironmentSettings();
371 nw::gfx::ResSceneEnvironmentSettingArray::iterator settingsEnd = settings.end();
372 for (nw::gfx::ResSceneEnvironmentSettingArray::iterator settingResource = settings.begin();
373 settingResource != settingsEnd; ++settingResource)
374 {
375 nw::gfx::SceneObject* sceneObject = nw::gfx::SceneBuilder()
376 .Resource(*settingResource)
377 .CreateObject(&s_DeviceAllocator, &s_DeviceAllocator);
378
379 nw::gfx::SceneEnvironmentSetting* sceneEnvironmentSetting =
380 nw::ut::DynamicCast<nw::gfx::SceneEnvironmentSetting*>(sceneObject);
381
382 NW_NULL_ASSERT(sceneEnvironmentSetting);
383 s_SceneEnvironmentSettings.push_back(sceneEnvironmentSetting);
384 }
385 }
386
387 /*!--------------------------------------------------------------------------*
388 @brief テンプレートとなるスケルタルモデルとアニメーションを作成します。
389 *---------------------------------------------------------------------------*/
390 void
BuildAnimModelTemplate()391 BuildAnimModelTemplate()
392 {
393 NW_NULL_ASSERT(s_AnimModelSetTemplate.skeletalModel);
394
395 nw::demo::ResourceSet* resourceSet = nw::demo::Utility::LoadResources(s_Resources, SKELETAL_ANIM_RESOURCE_FILES[0], &s_DeviceAllocator);
396 NW_ASSERT (resourceSet->resource.GetSkeletalAnimsCount() != 0);
397
398 s_AnimModelSetTemplate.skeletalModel->GetSkeleton()->GetResSkeleton().EnableFlags(nw::gfx::ResSkeletonData::FLAG_MODEL_COORDINATE);
399
400 s_AnimModelSetTemplate.resAnim = resourceSet->resource.GetSkeletalAnims(0);
401 s_AnimModelSetTemplate.evaluator = InitializeSkeletalAnim(s_AnimModelSetTemplate.skeletalModel, s_AnimModelSetTemplate.resAnim);
402 }
403
404 /*!--------------------------------------------------------------------------*
405 @brief 新しくモデルの生成する位置を求めます。
406 *---------------------------------------------------------------------------*/
407 void
GetNewDisplayPosition(f32 * pPosX,f32 * pPosZ)408 GetNewDisplayPosition(f32* pPosX, f32* pPosZ)
409 {
410 // モデルを渦巻状に配置していきます
411 int whirlSideLength = (s_WhirlDepth * 2 + 2);
412 int posX;
413 int posZ;
414
415 // 新しい位置が矩形のどの辺になるかを求めます
416 switch (s_WhirlPos / whirlSideLength)
417 {
418 case 0:
419 // 右辺
420 posX = s_WhirlDepth + 1;
421 posZ = s_WhirlPos % whirlSideLength - s_WhirlDepth;
422 break;
423 case 1:
424 // 上辺
425 posX = -(s_WhirlPos % whirlSideLength) + s_WhirlDepth;
426 posZ = s_WhirlDepth + 1;
427 break;
428 case 2:
429 // 左辺
430 posX = -s_WhirlDepth - 1;
431 posZ = -(s_WhirlPos % whirlSideLength) + s_WhirlDepth;
432 break;
433 case 3:
434 // 下辺
435 posX = s_WhirlPos % whirlSideLength - s_WhirlDepth;
436 posZ = -s_WhirlDepth - 1;
437 break;
438 default:
439 NW_ASSERT(false);
440 }
441
442 *pPosX = posX * 10.0f;
443 *pPosZ = posZ * 10.0f;
444
445 s_WhirlPos++;
446 if (s_WhirlPos >= whirlSideLength * 4)
447 {
448 s_WhirlDepth++;
449 s_WhirlPos = 0;
450 }
451 return;
452 }
453
454 /*!--------------------------------------------------------------------------*
455 @brief 次にモデルの生成する位置をひとつ戻します。
456 *---------------------------------------------------------------------------*/
457 void
ReleaseLastDisplayPosition()458 ReleaseLastDisplayPosition()
459 {
460 s_WhirlPos--;
461 if (s_WhirlPos < 0)
462 {
463 s_WhirlDepth--;
464 s_WhirlPos = (s_WhirlDepth * 2 + 2) * 4 - 1;
465 }
466
467 NW_ASSERT(s_WhirlDepth >= 0);
468 }
469
470 /*!--------------------------------------------------------------------------*
471 @brief モデルを複製します。
472 *---------------------------------------------------------------------------*/
473 void
DuplicateModel(DuplicationMode duplicationMode)474 DuplicateModel(DuplicationMode duplicationMode)
475 {
476 if (s_AnimModelSets.size() >= MAX_ANIM_MODELS)
477 {
478 return;
479 }
480
481 nw::gfx::SkeletalModel* skeletalModel;
482 AnimModelSet animModelSet;
483
484 switch (duplicationMode)
485 {
486 case SKELETON_SHARED:
487 // スケルトンを共有するスケルタルモデルのインスタンスを生成します。
488 // スケルトンを共有する場合、 FLAG_MODEL_COORDINATE フラグを ResSkelton に設定しておく必要があります。
489 // また、最初に生成されたスケルトンが所有権を持つので、スケルトンの破棄には注意が必要です。
490 // このデモでは s_AnimModelSetTemplate.skeletalModel がスケルトンの所有権を持ちます。
491 skeletalModel = nw::gfx::SkeletalModel::Builder()
492 .SharedSkeleton( s_AnimModelSetTemplate.skeletalModel->GetSkeleton() )
493 .SharedMaterialModel( s_AnimModelSetTemplate.skeletalModel )
494 .Create(NULL, nw::gfx::ResSceneObject(s_AnimModelSetTemplate.skeletalModel->GetResModel()), &s_DeviceAllocator);
495
496 NW_NULL_ASSERT(skeletalModel);
497
498 animModelSet.isSkeletonShared = true;
499 s_NumSkeletonSharedCopy++;
500 break;
501
502 case DUPLICATION:
503 // スケルタルモデルのインスタンスを生成します。
504 skeletalModel = nw::gfx::SkeletalModel::Builder()
505 .SharedMaterialModel( s_AnimModelSetTemplate.skeletalModel )
506 .Create(NULL, nw::gfx::ResSceneObject(s_AnimModelSetTemplate.skeletalModel->GetResModel()), &s_DeviceAllocator);
507
508 NW_NULL_ASSERT(skeletalModel);
509
510 animModelSet.isSkeletonShared = false;
511 s_NumCopy++;
512 break;
513
514 default:
515 NW_ASSERT(false);
516 }
517
518 if (s_ModelRoot->AttachChild(skeletalModel))
519 {
520 f32 posX;
521 f32 posZ;
522
523 animModelSet.skeletalModel = skeletalModel;
524 animModelSet.resAnim = s_AnimModelSetTemplate.resAnim;
525 switch (duplicationMode)
526 {
527 case SKELETON_SHARED:
528 // スケルトンを共有する場合、共有スケルトンの1つにアニメーション評価をすればよいので、
529 // 複製のスケルトンにはアニメーション評価の作成やバインドを行いません。
530 animModelSet.evaluator = NULL;
531 break;
532
533 case DUPLICATION:
534 animModelSet.evaluator = InitializeSkeletalAnim(animModelSet.skeletalModel, animModelSet.resAnim);
535 NW_NULL_ASSERT(animModelSet.evaluator);
536 break;
537 }
538 s_AnimModelSets.push_back( animModelSet );
539
540 GetNewDisplayPosition(&posX, &posZ);
541 skeletalModel->Transform().SetTranslate(posX, 0.0f, posZ);
542
543 // シーン構造が変化したので初期化を行います。
544 s_SceneSystem->InitializeScene(s_SceneRoot);
545 }
546 else
547 {
548 nw::ut::SafeDestroy(skeletalModel);
549 }
550 }
551
552 /*!--------------------------------------------------------------------------*
553 @brief 最後に複製したモデルを破棄します。
554 *---------------------------------------------------------------------------*/
555 void
DestroyLastDuplicatedModel()556 DestroyLastDuplicatedModel()
557 {
558 if (s_AnimModelSets.empty())
559 {
560 return;
561 }
562
563 AnimModelSet destroyModelSet = s_AnimModelSets.back();
564 s_AnimModelSets.pop_back();
565
566 s_ModelRoot->DetachChild(destroyModelSet.skeletalModel);
567
568 nw::ut::SafeDestroy(destroyModelSet.skeletalModel);
569 nw::ut::SafeDestroy(destroyModelSet.evaluator);
570
571 s_SceneSystem->InitializeScene(s_SceneRoot);
572
573 ReleaseLastDisplayPosition();
574
575 if (destroyModelSet.isSkeletonShared)
576 {
577 s_NumSkeletonSharedCopy--;
578 }
579 else
580 {
581 s_NumCopy--;
582 }
583 }
584
585 /*!--------------------------------------------------------------------------*
586 @brief シーンを初期化します。
587 *---------------------------------------------------------------------------*/
588 void
InitializeScenes()589 InitializeScenes()
590 {
591 s_AnimModelSetTemplate.skeletalModel = NULL;
592
593 BuildRootNodes();
594
595 BuildCameras();
596
597 NW_FOREACH(const wchar_t* name, MODEL_RESOURCE_FILES)
598 {
599 BuildResources(nw::demo::Utility::LoadResources(s_Resources, name, &s_DeviceAllocator));
600 }
601
602 BuildAnimModelTemplate();
603
604 s_NumCopy = 0;
605 s_NumSkeletonSharedCopy = 0;
606
607 // シーンツリーを巡回して初期化を行います。
608 s_SceneSystem->InitializeScene(s_SceneRoot);
609 s_SceneSystem->UpdateScene();
610
611 // シーン環境の参照解決を行い設定します。
612 s_RenderSystem->SetSceneEnvironmentSettings(s_SceneSystem, &s_SceneEnvironmentSettings);
613
614 // カメラを設定します。
615 nw::gfx::SceneEnvironment& sceneEnvironment = s_RenderSystem->GetSceneEnvironment();
616 sceneEnvironment.SetCamera(s_BaseCameraIndex, s_BaseCamera);
617 nw::demo::Utility::SetCameraAspectRatio(s_BaseCamera, s_RenderTargets[0]);
618
619 NW_GL_ASSERT();
620
621 s_FrameCount = 0;
622
623 s_WhirlDepth = 0;
624 s_WhirlPos = 0;
625
626 // あらかじめ何体か配置しておきます。
627 DuplicateModel(SKELETON_SHARED);
628 DuplicateModel(SKELETON_SHARED);
629 DuplicateModel(DUPLICATION);
630 DuplicateModel(DUPLICATION);
631 DuplicateModel(DUPLICATION);
632 }
633
634 /*!--------------------------------------------------------------------------*
635 @brief シーン関連の後始末をします。
636 *---------------------------------------------------------------------------*/
637 void
TerminateScenes()638 TerminateScenes()
639 {
640 nw::gfx::SafeDestroyBranch(s_SceneRoot);
641 nw::demo::SafeCleanupResources(s_Resources);
642 nw::ut::SafeDestroyAll(s_SceneEnvironmentSettings);
643
644 TerminateAnim();
645
646 NW_GL_ASSERT();
647
648 s_Resources.clear();
649 s_SceneEnvironmentSettings.clear();
650 s_ModelRoot = NULL;
651 }
652
653 /*!--------------------------------------------------------------------------*
654 @brief モデルの生成・破棄や操作を行います。
655 *---------------------------------------------------------------------------*/
656 void
ControlModels()657 ControlModels()
658 {
659 if (nw::demo::PadFactory::GetPad()->IsButtonRepeatFast(nw::demo::Pad::BUTTON_L))
660 {
661 // Lボタンでモデルを生成します。
662 // 十字キーの上を押しながらLボタンを押すとスケルトンを共有するモデルを生成します。
663 if (nw::demo::PadFactory::GetPad()->IsButtonPress(nw::demo::Pad::BUTTON_UP))
664 {
665 DuplicateModel(SKELETON_SHARED);
666 }
667 else
668 {
669 DuplicateModel(DUPLICATION);
670 }
671 }
672 else if (nw::demo::PadFactory::GetPad()->IsButtonRepeatFast(nw::demo::Pad::BUTTON_R))
673 {
674 // 最後に生成したモデルを破棄します。
675 DestroyLastDuplicatedModel();
676 }
677 }
678
679 /*!--------------------------------------------------------------------------*
680 @brief シーンを更新します。
681 *---------------------------------------------------------------------------*/
682 void
UpdateScene()683 UpdateScene()
684 {
685 ControlModels();
686
687 s_SceneSystem->GetCameraController()->Update();
688
689 s_SceneSystem->UpdateScene();
690
691 s_BaseCamera->UpdateCameraMatrix();
692
693 s_RenderSystem->CalcStereoCamera(s_LeftCamera, s_RightCamera, s_BaseCamera, s_fNearPlane + 5.0f);
694
695 ++s_FrameCount;
696 }
697
698 /*!--------------------------------------------------------------------------*
699 @brief 負荷表示やテスト機能の処理をおこないます。
700 *---------------------------------------------------------------------------*/
701 void
ReportDemo()702 ReportDemo()
703 {
704 NW_PROFILE("ReportDemo");
705
706 // 負荷表示からはこれらの負荷は除きます。
707 s_RenderSystem->SuspendLoadMeter();
708
709 nw::demo::DebugUtility::CalcLoadMeter(s_RenderSystem);
710
711 s_GraphicsDrawing.BeginDrawingShape();
712
713 nw::demo::DebugUtility::DrawLoadMeter(
714 s_RenderSystem,
715 &s_GraphicsDrawing
716 );
717
718 s_GraphicsDrawing.EndDrawingShape();
719
720 s_GraphicsDrawing.BeginDrawingString();
721
722 nw::demo::DebugUtility::DrawLoadMeterText(
723 s_RenderSystem,
724 &s_GraphicsDrawing
725 );
726
727 const int dumpPositionX = 10;
728 const int dumpPositionY = 10;
729 s_GraphicsDrawing.DrawString(
730 dumpPositionX,
731 dumpPositionY,
732 " original: 1\n"
733 " copy: %d\n"
734 "skeleton shared: %d",
735 s_NumCopy,
736 s_NumSkeletonSharedCopy
737 );
738
739 s_GraphicsDrawing.EndDrawingString();
740
741 s_RenderSystem->ResumeLoadMeter();
742 }
743
744 /*!--------------------------------------------------------------------------*
745 @brief シーンをデモンストレーションします。
746 *---------------------------------------------------------------------------*/
747 void
DemoScene()748 DemoScene()
749 {
750 NW_ASSERT(!s_RenderTargets.empty());
751
752 nw::gfx::RenderContext* renderContext = s_RenderSystem->GetRenderContext();
753
754 InitializeScenes();
755
756 nw::demo::DebugUtility::PostInitializeScenes();
757
758 NW_LOG("[Multi Instance Demo usage]\n");
759 NW_LOG("r : delete\n");
760 NW_LOG("l : add copy\n");
761 NW_LOG("up + l : add skeleton shared copy\n");
762
763 bool isContinuing = true;
764
765 while ( isContinuing )
766 {
767 nw::demo::DebugUtility::AdvanceAutoTestFrame();
768
769 nw::demo::PadFactory::GetPad()->Update();
770
771 UpdateScene();
772
773 renderContext->SetActiveCamera(s_BaseCameraIndex);
774 s_RenderSystem->SubmitView(s_SceneSystem);
775
776 s_RenderSystem->SetRenderTarget(s_RenderTargets[0]);
777 s_RenderSystem->RenderStereoScene(s_LeftCamera, s_RightCamera);
778
779 s_RenderSystem->ClearBySkyModel(s_BaseCamera);
780 ReportDemo();
781 s_RenderSystem->TransferBuffer(nw::demo::LOWER_SCREEN);
782
783 s_RenderSystem->PresentBuffer(nw::demo::UPPER_SCREEN | nw::demo::LOWER_SCREEN | nw::demo::EXTENSION_SCREEN);
784
785 renderContext->ResetState();
786
787 if (nw::demo::Utility::IsTerminating())
788 {
789 isContinuing = false;
790 }
791 }
792
793 nw::demo::DebugUtility::PreTerminateScenes();
794
795 TerminateScenes();
796 }
797
798 } // namespace
799
800 /*!--------------------------------------------------------------------------*
801 @brief メイン関数です。
802 *---------------------------------------------------------------------------*/
803 void
nnMain()804 nnMain()
805 {
806 nw::demo::InitializeGraphicsSystem(&s_DeviceAllocator);
807
808 nw::demo::PadFactory::Initialize(&s_DeviceAllocator);
809
810 NW_DEMO_TEST_LOOP(&s_DeviceAllocator, NULL, &s_RenderSystem)
811 {
812 InitializeGraphics();
813
814 DemoScene();
815
816 TerminateGraphics();
817 }
818
819 nw::demo::PadFactory::Finalize();
820
821 nw::demo::FinalizeGraphicsSystem();
822 }
823