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