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