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