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