1 /*---------------------------------------------------------------------------*
2 Project: NintendoWare
3 File: LowLayerAnimationDemo.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 #include <nn/gx.h>
23
24 #include <nw/types.h>
25 #include <nw/demo.h>
26 #include <nw/dev.h>
27 #include <nw/gfx.h>
28 #include <nw/ut.h>
29
30 namespace
31 {
32
33 //----------------------------------------
34 // メモリ関係
35 // デモではデバイスメモリから全てのメモリを確保するようになっています。
36
37 // デモで使用するメモリサイズです。
38 const size_t DEMO_MEMORY_SIZE = 0x1000000;
39
40 // デバイスメモリを確保するためのアロケータです。
41 nw::demo::DemoAllocator s_DeviceAllocator;
42
43 nw::demo::GraphicsMemoryAllocator s_GraphicsMemoryAllocator;
44
45 const int MAX_FILE = 256;
46 const int MAX_DIRECTORY = 16;
47
48 //----------------------------------------
49 // ファイル名の定義です。
50 static const wchar_t* MODEL_RESOURCE_FILES[] =
51 {
52 NW_DEMO_FILE_PATH(L"Male.bcmdl"),
53 NW_DEMO_FILE_PATH(L"Walk.bcskla"),
54 NW_DEMO_FILE_PATH(L"FragmentLight.bcenv"),
55 };
56
57 //----------------------------------------
58 // 描画関係
59 nw::gfx::IRenderTarget* s_RenderTarget = NULL;
60
61 nw::gfx::RenderContext* s_RenderContext = NULL;
62 nw::gfx::MeshRenderer* s_MeshRenderer = NULL;
63 nw::demo::DisplayBufferSwapper* s_UpperSwapper = NULL;
64 nw::demo::DisplayBufferSwapper* s_ExtensionSwapper = NULL;
65
66 const size_t COMMAND_BUFFER_SIZE = 0x100000;
67 const size_t REQUEST_COUNT = 512;
68 nw::demo::CommandListSwapper* s_CommandListSwapper = NULL;
69
70 //----------------------------------------
71 // リソース関係
72 const int RESOURCES_COUNT = 3;
73 struct ResourceSet
74 {
75 nw::ut::MoveArray<u8> buffer;
76 nw::gfx::ResGraphicsFile resource;
77 };
78 typedef nw::ut::FixedSizeArray<ResourceSet, RESOURCES_COUNT> ResourceArray;
79
80 ResourceArray s_Resources;
81
82 //----------------------------------------
83 // シーン関係
84 s32 s_FrameCount = 0;
85 nw::gfx::WorldMatrixUpdater* s_WorldMatrixUpdater = NULL;
86 nw::gfx::SkeletonUpdater* s_SkeletonUpdater = NULL;
87 nw::gfx::BillboardUpdater* s_BillboardUpdater = NULL;
88
89 const s32 s_BaseCameraIndex = 0;
90 nw::gfx::Camera* s_BaseCamera = NULL;
91 nw::gfx::Camera* s_LeftCamera = NULL;
92 nw::gfx::Camera* s_RightCamera = NULL;
93 const f32 s_NearPlane = 0.1f;
94
95 nw::demo::CameraController* s_CameraController = NULL;
96
97 nn::ulcd::CTR::StereoCamera* s_StereoCamera;
98
99 const int MODEL_COUNT = 1;
100 const int LIGHT_COUNT = 1;
101
102 typedef nw::ut::FixedSizeArray<nw::gfx::SkeletalModel*, MODEL_COUNT> SkeletalModelArray;
103 typedef nw::ut::FixedSizeArray<nw::gfx::FragmentLight*, LIGHT_COUNT> FragmentLightArray;
104
105 SkeletalModelArray s_SkeletalModels;
106 FragmentLightArray s_FragmentLights;
107
108 //----------------------------------------
109 // アニメーション関係
110 nw::gfx::AnimObject* s_AnimObject;
111
112 const int ANIMATION_RESOURCES_COUNT = 3;
113 nw::ut::FixedSizeArray<nw::gfx::ResGraphicsFile, ANIMATION_RESOURCES_COUNT> s_ResAnims;
114
115 void UpdateNode(nw::gfx::TransformNode* node);
116
117 /*!--------------------------------------------------------------------------*
118 @brief グラフィックスメモリのアロケータです。
119
120 関数ポインタが nngxInitialize の引数として使用されます。
121 *---------------------------------------------------------------------------*/
AllocateGraphicsMemory(GLenum area,GLenum aim,GLuint id,GLsizei size)122 void* AllocateGraphicsMemory(GLenum area, GLenum aim, GLuint id, GLsizei size)
123 {
124 void* buffer = s_GraphicsMemoryAllocator.Allocate(area, aim, id, size);
125 return buffer;
126 }
127
128 /*!--------------------------------------------------------------------------*
129 @brief グラフィックスメモリのデアロケータです。
130
131 関数ポインタが nngxInitialize の引数として使用されます。
132 *---------------------------------------------------------------------------*/
DeallocateGraphicsMemory(GLenum area,GLenum aim,GLuint id,void * addr)133 void DeallocateGraphicsMemory(GLenum area, GLenum aim, GLuint id, void* addr)
134 {
135 s_GraphicsMemoryAllocator.Deallocate(area, aim, id, addr);
136 }
137
138 /*!--------------------------------------------------------------------------*
139 @brief グラフィックスシステムに必要なメモリなどの初期化を行います。
140 *---------------------------------------------------------------------------*/
141 void
InitializeGraphicsSystem()142 InitializeGraphicsSystem()
143 {
144 nn::os::Initialize();
145 nn::fs::Initialize();
146
147 nw::demo::InitializeDemoMemory();
148
149 nw::demo::InitializeDemoAllocator(&s_DeviceAllocator, DEMO_MEMORY_SIZE, nn::os::ALLOCATE_OPTION_LINEAR);
150
151 // デバイスメモリを用いるグラフィックスメモリアロケータを初期化します。
152 s_GraphicsMemoryAllocator.Initialize(&s_DeviceAllocator);
153
154 s32 workingMemorySize = nn::fs::GetRomRequiredMemorySize(MAX_FILE, MAX_DIRECTORY);
155 NW_ASSERT(workingMemorySize != 0);
156 void* workingMemory = nw::demo::Alloc(workingMemorySize);
157 nn::Result result = nn::fs::MountRom(MAX_FILE, MAX_DIRECTORY, workingMemory, workingMemorySize);
158
159 NW_ASSERT(result.IsSuccess());
160 }
161
162 /*!--------------------------------------------------------------------------*
163 @brief グラフィックスシステムに必要なメモリなどの終了処理を行います。
164 *---------------------------------------------------------------------------*/
165 void
FinalizeGraphicsSystem()166 FinalizeGraphicsSystem()
167 {
168 s_GraphicsMemoryAllocator.Finalize();
169
170 nw::demo::FinalizeDemoAllocator(&s_DeviceAllocator);
171 }
172
173 /*!--------------------------------------------------------------------------*
174 @brief グラフィックス関連の初期化を行います。
175 *---------------------------------------------------------------------------*/
176 void
InitializeGraphics()177 InitializeGraphics()
178 {
179 if (nngxInitialize(AllocateGraphicsMemory, DeallocateGraphicsMemory) == GL_FALSE)
180 {
181 NW_FATAL_ERROR("nngxInitialize failed.\n");
182 }
183
184 //-----------------------------
185 nw::demo::DisplayBufferSwapper::Description upperScreenDescription;
186 upperScreenDescription.screenKind = nw::demo::UPPER_SCREEN;
187 upperScreenDescription.width = 400;
188 upperScreenDescription.height = 240;
189 upperScreenDescription.bufferCount = 2;
190
191 nw::demo::DisplayBufferSwapper::Description extensionScreenDescription;
192 extensionScreenDescription.screenKind = nw::demo::EXTENSION_SCREEN;
193 extensionScreenDescription.width = upperScreenDescription.width;
194 extensionScreenDescription.height = upperScreenDescription.height;
195 extensionScreenDescription.bufferCount = upperScreenDescription.bufferCount;
196
197 s_UpperSwapper = nw::demo::DisplayBufferSwapper::Builder()
198 .BufferDescription(upperScreenDescription)
199 .Create(&s_DeviceAllocator);
200
201 s_ExtensionSwapper = nw::demo::DisplayBufferSwapper::Builder()
202 .BufferDescription(extensionScreenDescription)
203 .Create(&s_DeviceAllocator);
204
205 //-----------------------------
206 nw::demo::CommandListSwapper::Description commandListSwapperDescription;
207 commandListSwapperDescription.commandListCount = 1;
208 commandListSwapperDescription.bufferSize = COMMAND_BUFFER_SIZE;
209 commandListSwapperDescription.requestCount = REQUEST_COUNT;
210 commandListSwapperDescription.reusableBufferSize = COMMAND_BUFFER_SIZE;
211 commandListSwapperDescription.reusableRequestCount = REQUEST_COUNT;
212 commandListSwapperDescription.maxGpuProfilingEntryCount = 0;
213 s_CommandListSwapper =
214 nw::demo::CommandListSwapper::Create(&s_DeviceAllocator, commandListSwapperDescription);
215 s_CommandListSwapper->Bind();
216
217 //-----------------------------
218 nngxSetDisplayMode(nw::demo::UPPER_SCREEN_MODE_STEREO);
219
220 //-----------------------------
221 nw::gfx::CommandCacheManager::SetAllocator( &s_DeviceAllocator );
222
223 //-----------------------------
224 s_RenderContext = nw::gfx::RenderContext::Builder()
225 .Create(&s_DeviceAllocator);
226
227 //-----------------------------
228 void* cameraMemory = s_DeviceAllocator.Alloc(sizeof(nn::ulcd::CTR::StereoCamera));
229 s_StereoCamera = new(cameraMemory) nn::ulcd::CTR::StereoCamera();
230 s_StereoCamera->Initialize();
231
232 //-----------------------------
233 s_MeshRenderer = nw::gfx::MeshRenderer::Create(&s_DeviceAllocator);
234 s_MeshRenderer->SetRenderContext(s_RenderContext);
235
236 //-----------------------------
237 nw::gfx::RenderColorFormat renderColorFormat = nw::gfx::RENDER_COLOR_FORMAT_RGBA8;
238 s_RenderTarget =
239 nw::gfx::IRenderTarget::Builder()
240 .BufferSize(upperScreenDescription.height, upperScreenDescription.width)
241 .ColorFormat(renderColorFormat)
242 .Create(&s_DeviceAllocator);
243 NW_NULL_ASSERT(s_RenderTarget);
244
245 //-----------------------------
246 s_WorldMatrixUpdater = nw::gfx::WorldMatrixUpdater::Builder()
247 .Create(&s_DeviceAllocator);
248
249 //-----------------------------
250 // スケルトンアップデータを生成します。
251 s_SkeletonUpdater = nw::gfx::SkeletonUpdater::Builder()
252 .Create(&s_DeviceAllocator);
253
254 // スケルタルモデルの更新に必要なビルボードアップデータを生成します。
255 s_BillboardUpdater = nw::gfx::BillboardUpdater::Create(&s_DeviceAllocator);
256
257 //-----------------------------
258 nngxStartLcdDisplay();
259
260 NW_GL_ASSERT();
261 }
262 /*!--------------------------------------------------------------------------*
263 @brief グラフィックス関連の後始末をします。
264 *---------------------------------------------------------------------------*/
265 void
TerminateGraphics()266 TerminateGraphics()
267 {
268 s_StereoCamera->Finalize();
269 s_DeviceAllocator.Free(s_StereoCamera);
270
271 nw::gfx::SafeDestroy(s_SkeletonUpdater);
272 nw::gfx::SafeDestroy(s_WorldMatrixUpdater);
273
274 nw::gfx::SafeDestroy(s_RenderTarget);
275
276 nw::gfx::SafeDestroy(s_MeshRenderer);
277 nw::gfx::SafeDestroy(s_CommandListSwapper);
278 nw::gfx::SafeDestroy(s_UpperSwapper);
279 nw::gfx::SafeDestroy(s_ExtensionSwapper);
280 nw::gfx::SafeDestroy(s_RenderContext);
281
282 nw::gfx::SafeDestroy(s_BillboardUpdater);
283
284 nngxFinalize();
285 s_GraphicsMemoryAllocator.Finalize();
286
287 NW_GL_ASSERT();
288 }
289
290 /*!--------------------------------------------------------------------------*
291 @brief グラフィックスリソースをロードします。
292
293 @param[in] resourcePath ファイルのパス名
294
295 @return ロードしたグラフィックス情報を返します。
296 *---------------------------------------------------------------------------*/
297 ResourceSet*
LoadResources(const wchar_t * resourcePath)298 LoadResources(const wchar_t* resourcePath)
299 {
300 ResourceSet resourceSet;
301 // 現在、デバイスメモリ上に読み込む方式にのみ対応しています。
302 // テクスチャをロードするには128byteアライメントを行う必要があります。
303 static const int resourceAlignment = 128;
304 resourceSet.buffer = nw::demo::Utility::LoadFile(&s_DeviceAllocator , resourcePath, resourceAlignment);
305
306 if (!resourceSet.buffer)
307 {
308 return NULL;
309 }
310
311 resourceSet.resource = nw::gfx::ResGraphicsFile(&(resourceSet.buffer.front()));
312
313 bool isPushed = s_Resources.push_back(resourceSet);
314
315 NW_ASSERT(isPushed);
316
317 return &(s_Resources.back());
318 }
319
320 /*!--------------------------------------------------------------------------*
321 @brief シーンノードを生成します。
322
323 @param[in] resource シーンノードのリソースです。
324
325 @return 生成したシーンノードです。。
326 *---------------------------------------------------------------------------*/
327 nw::gfx::SceneNode*
CreateSceneNode(nw::gfx::ResSceneObject resource)328 CreateSceneNode(nw::gfx::ResSceneObject resource)
329 {
330 nw::gfx::SceneObject* sceneObject = nw::gfx::SceneBuilder()
331 .Resource(resource)
332 .MaxChildren(0)
333 .CreateObject(&s_DeviceAllocator, &s_DeviceAllocator);
334
335 return nw::ut::DynamicCast<nw::gfx::SceneNode*>(sceneObject);
336 }
337
338 /*!--------------------------------------------------------------------------*
339 @brief リソース関連の構築をします。
340 *---------------------------------------------------------------------------*/
341 void
BuildResources(ResourceSet * resourceSet)342 BuildResources(ResourceSet* resourceSet)
343 {
344 resourceSet->resource.ForeachTexture(nw::gfx::LocationFlagSetter(NN_GX_MEM_VRAMA | GL_NO_COPY_FCRAM_DMP));
345 resourceSet->resource.ForeachIndexStream(nw::gfx::LocationFlagSetter(NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP));
346 resourceSet->resource.ForeachVertexStream(nw::gfx::LocationFlagSetter(NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP));
347
348 nw::gfx::Result result = resourceSet->resource.Setup(&s_DeviceAllocator);
349 if (result.IsFailure())
350 {
351 NW_FATAL_ERROR("Fail to set up model. A result code is 0x%x", result.GetCode());
352 }
353
354 nw::gfx::ResModelArray models = resourceSet->resource.GetModels();
355 nw::gfx::ResModelArray::iterator modelsEnd = models.end();
356 for (nw::gfx::ResModelArray::iterator modelResource = models.begin();
357 modelResource != modelsEnd; ++modelResource)
358 {
359 nw::gfx::SceneNode* node = CreateSceneNode(*modelResource);
360 NW_NULL_ASSERT(node);
361 NW_ASSERT(nw::ut::IsTypeOf<nw::gfx::SkeletalModel>(node));
362
363 s_SkeletalModels.push_back(static_cast<nw::gfx::SkeletalModel*>(node));
364 }
365
366 nw::gfx::ResLightArray lights = resourceSet->resource.GetLights();
367 for (nw::gfx::ResLightArray::iterator lightResource = lights.begin();
368 lightResource != lights.end(); ++lightResource)
369 {
370 nw::gfx::SceneNode* node = CreateSceneNode(*lightResource);
371 NW_NULL_ASSERT(node);
372 NW_ASSERT(nw::ut::IsTypeOf<nw::gfx::FragmentLight>(node));
373
374 s_FragmentLights.push_back(static_cast<nw::gfx::FragmentLight*>(node));
375 }
376 }
377
378 /*!--------------------------------------------------------------------------*
379 @brief カメラの構築をします。
380 *---------------------------------------------------------------------------*/
381 void
BuildCameras()382 BuildCameras()
383 {
384 nw::gfx::LookAtTargetViewUpdater* viewUpdater
385 = nw::gfx::LookAtTargetViewUpdater::Create(&s_DeviceAllocator);
386
387 nw::gfx::ResLookAtTargetViewUpdater resViewUpdater =
388 nw::gfx::ResStaticCast<nw::gfx::ResLookAtTargetViewUpdater>(
389 viewUpdater->GetResource());
390 resViewUpdater.SetTargetPosition(0.0f,10.0f,0.0f);
391 resViewUpdater.SetUpwardVector(0.0f,1.0f,0.0f);
392
393 nw::gfx::PerspectiveProjectionUpdater* projectionUpdater
394 = nw::gfx::PerspectiveProjectionUpdater::Create(&s_DeviceAllocator);
395
396 nw::gfx::ResPerspectiveProjectionUpdater resProjectionUpdater =
397 nw::gfx::ResStaticCast<nw::gfx::ResPerspectiveProjectionUpdater>(
398 projectionUpdater->GetResource());
399 resProjectionUpdater.SetNear(s_NearPlane);
400 resProjectionUpdater.SetFar(1000.0f);
401 resProjectionUpdater.SetFovy(NW_MATH_DEG_TO_RAD(37.8f));
402
403 resProjectionUpdater.SetAspectRatio(
404 static_cast<f32>(s_RenderTarget->GetDescription().height) /
405 static_cast<f32>(s_RenderTarget->GetDescription().width));
406
407 s_BaseCamera =
408 nw::gfx::Camera::DynamicBuilder()
409 .MaxChildren(0)
410 .MaxCallbacks(0)
411 .ViewUpdater(viewUpdater)
412 .ProjectionUpdater(projectionUpdater)
413 .Create(&s_DeviceAllocator);
414 NW_POINTER_ASSERT(s_BaseCamera);
415 s_BaseCamera->Transform().SetTranslate(nw::math::VEC3(20.0f, 15.0f, 20.0f));
416
417 s_LeftCamera =
418 nw::gfx::Camera::DynamicBuilder()
419 .MaxChildren(0)
420 .MaxCallbacks(0)
421 .Create(&s_DeviceAllocator);
422 NW_POINTER_ASSERT(s_LeftCamera);
423
424 s_RightCamera =
425 nw::gfx::Camera::DynamicBuilder()
426 .MaxChildren(0)
427 .MaxCallbacks(0)
428 .Create(&s_DeviceAllocator);
429 NW_POINTER_ASSERT(s_RightCamera);
430
431 s_CameraController =
432 nw::demo::CameraController::Builder()
433 .MaxCameraCount(1)
434 .Create(&s_DeviceAllocator);
435 s_CameraController->Register(s_BaseCamera);
436 }
437
438 /*!--------------------------------------------------------------------------*
439 @brief アニメーション関連の構築をします。
440 *---------------------------------------------------------------------------*/
441 void
BuildAnimations()442 BuildAnimations()
443 {
444 s_AnimObject = nw::demo::Utility::BindAnimationByName(
445 &s_DeviceAllocator,
446 s_SkeletalModels,
447 s_ResAnims,
448 "Male",
449 "Walk",
450 nw::demo::Utility::SKELETAL_ANIMATION,
451 false);
452 }
453
454 /*!--------------------------------------------------------------------------*
455 @brief シーンを初期化します。
456 *---------------------------------------------------------------------------*/
457 void
InitializeScenes()458 InitializeScenes()
459 {
460 BuildCameras();
461
462 NW_FOREACH(const wchar_t* name, MODEL_RESOURCE_FILES)
463 {
464 ResourceSet* resourceSet = LoadResources(name);
465 BuildResources(resourceSet);
466 s_ResAnims.push_back(resourceSet->resource);
467 }
468
469 NW_GL_ASSERT();
470
471 BuildAnimations();
472
473 s_FrameCount = 0;
474 }
475
476 /*!--------------------------------------------------------------------------*
477 @brief シーン関連の後始末をします。
478 *---------------------------------------------------------------------------*/
479 void
TerminateScenes()480 TerminateScenes()
481 {
482 nw::gfx::SafeDestroyAll(s_FragmentLights);
483 nw::gfx::SafeDestroyAll(s_SkeletalModels);
484 nw::demo::SafeCleanupResources(s_Resources);
485 nw::gfx::SafeDestroy(s_BaseCamera);
486 nw::gfx::SafeDestroy(s_LeftCamera);
487 nw::gfx::SafeDestroy(s_RightCamera);
488 nw::gfx::SafeDestroy(s_CameraController);
489 nw::gfx::SafeDestroy(s_AnimObject);
490
491 NW_GL_ASSERT();
492
493 s_Resources.clear();
494 s_ResAnims.clear();
495 }
496
497 /*!--------------------------------------------------------------------------*
498 @brief ノードを更新します。
499 *---------------------------------------------------------------------------*/
500 void
UpdateNode(nw::gfx::TransformNode * node)501 UpdateNode(nw::gfx::TransformNode* node)
502 {
503 // 一度計算したら計算処理をスキップする。
504 // ただし、ツリー構造は正しく解釈されない。
505 if (node->Transform().IsEnabledFlags(nw::gfx::CalculatedTransform::FLAG_IS_DIRTY))
506 {
507 s_WorldMatrixUpdater->UpdateBasic(
508 &node->WorldMatrix(),
509 &node->WorldTransform(),
510 node->Transform(),
511 nw::gfx::CalculatedTransform::Identity(),
512 nw::gfx::CalculatedTransform::Identity());
513
514 node->Transform().DisableFlags(nw::gfx::CalculatedTransform::FLAG_IS_DIRTY);
515 }
516 }
517
518 /*!--------------------------------------------------------------------------*
519 @brief カメラを更新します。
520 *---------------------------------------------------------------------------*/
UpdateCamera()521 void UpdateCamera()
522 {
523 s_CameraController->Update();
524 UpdateNode(s_BaseCamera);
525 s_BaseCamera->UpdateCameraMatrix();
526
527 // ステレオカメラの計算
528 NW_NULL_ASSERT(s_LeftCamera);
529 NW_NULL_ASSERT(s_RightCamera);
530 NW_NULL_ASSERT(s_BaseCamera);
531 nn::math::MTX44& projOriginal = s_BaseCamera->ProjectionMatrix();
532 nn::math::MTX34& viewOriginal = s_BaseCamera->ViewMatrix();
533 nn::math::MTX44& projL = s_LeftCamera->ProjectionMatrix();
534 nn::math::MTX34& viewL = s_LeftCamera->ViewMatrix();
535 nn::math::MTX44& projR = s_RightCamera->ProjectionMatrix();
536 nn::math::MTX34& viewR = s_RightCamera->ViewMatrix();
537
538 // Ortho カメラでは別の処理を行う必要があります。
539 // 例として demo::RenderSystem::CalcStereoCamera() を参照してください。
540 const f32 DEPTH_LEVEL = 5.0f + s_NearPlane;
541 const f32 DEPTH_RANGE = 1.0f;
542 s_StereoCamera->CalculateMatrices(
543 &projL,
544 &viewL,
545 &projR,
546 &viewR,
547 &projOriginal,
548 &viewOriginal,
549 DEPTH_LEVEL,
550 DEPTH_RANGE,
551 false);
552 }
553
554 /*!--------------------------------------------------------------------------*
555 @brief 生成されたノードを更新します。
556 *---------------------------------------------------------------------------*/
UpdateNodes()557 void UpdateNodes()
558 {
559 // フラグメントライト更新
560 FragmentLightArray::iterator lightEnd = s_FragmentLights.end();
561 for (FragmentLightArray::iterator light = s_FragmentLights.begin(); light != lightEnd; ++light)
562 {
563 UpdateNode(*light);
564 }
565
566
567 // スケルタルモデル更新
568 SkeletalModelArray::iterator skeletalModelEnd = s_SkeletalModels.end();
569 for (SkeletalModelArray::iterator model = s_SkeletalModels.begin(); model != skeletalModelEnd; ++model)
570 {
571 UpdateNode(*model);
572
573 // フルベイクアニメを使用する場合は処理をスキップします。
574 if ((*model)->GetFullBakedAnimEnabled()) { continue; }
575
576 // スケルトンが既に更新済みの場合は処理をスキップします。
577 if ((*model)->GetSkeleton()->IsUpdated()) { continue; }
578
579 // スケルトンを更新します。
580 s_SkeletonUpdater->UpdateWorld((*model)->GetSkeleton(), *s_WorldMatrixUpdater);
581
582 // スケルトンが更新済みであることを表すフラグを true にします。
583 (*model)->GetSkeleton()->SetUpdated(true);
584 }
585 }
586
587 /*!--------------------------------------------------------------------------*
588 @brief アニメーションを評価します。
589 *---------------------------------------------------------------------------*/
590 void
EvaluateSkeletalAnim()591 EvaluateSkeletalAnim()
592 {
593 SkeletalModelArray::iterator skeletalModelEnd = s_SkeletalModels.end();
594 for (SkeletalModelArray::iterator model = s_SkeletalModels.begin(); model != skeletalModelEnd; ++model)
595 {
596 (*model)->GetAnimBinding()->Evaluate(nw::anim::ResGraphicsAnimGroup::EVALUATION_BEFORE_WORLD_UPDATE);
597 (*model)->GetAnimBinding()->Evaluate(nw::anim::ResGraphicsAnimGroup::EVALUATION_AFTER_SCENE_CULLING);
598 }
599 }
600
601 /*!--------------------------------------------------------------------------*
602 @brief アニメーションのフレームを更新します。
603 *---------------------------------------------------------------------------*/
604 void
UpdateFrame()605 UpdateFrame()
606 {
607 SkeletalModelArray::iterator skeletalModelEnd = s_SkeletalModels.end();
608 for (SkeletalModelArray::iterator model = s_SkeletalModels.begin(); model != skeletalModelEnd; ++model)
609 {
610 (*model)->UpdateFrame();
611 }
612 }
613
614 /*!--------------------------------------------------------------------------*
615 @brief シーンを更新します。
616 *---------------------------------------------------------------------------*/
617 void
UpdateScene()618 UpdateScene()
619 {
620 EvaluateSkeletalAnim();
621
622 UpdateNodes();
623
624 UpdateFrame();
625
626 UpdateCamera();
627
628 ++s_FrameCount;
629 }
630
631 /*!--------------------------------------------------------------------------*
632 @brief カメラ、ライト、フォグなどのシーン環境を設定します。
633 *---------------------------------------------------------------------------*/
634 void
SetEnvironment()635 SetEnvironment()
636 {
637 nw::gfx::SceneEnvironment& sceneEnvironment = s_RenderContext->GetSceneEnvironment();
638 sceneEnvironment.SetCamera(s_BaseCameraIndex, s_BaseCamera);
639
640 //-----------------------------
641 FragmentLightArray::iterator lightEnd = s_FragmentLights.end();
642 for (FragmentLightArray::iterator light = s_FragmentLights.begin(); light != lightEnd; ++light)
643 {
644 sceneEnvironment.SetFragmentLight(*light);
645 }
646 }
647
648 /*!--------------------------------------------------------------------------*
649 @brief ビューに関連する更新処理を行います。
650 *---------------------------------------------------------------------------*/
651 void
SubmitView()652 SubmitView()
653 {
654 SkeletalModelArray::iterator skeletalModelEnd = s_SkeletalModels.end();
655 for (SkeletalModelArray::iterator model = s_SkeletalModels.begin(); model != skeletalModelEnd; ++model)
656 {
657 // スケルトンが更新済みであることを表すフラグを false に戻します。
658 (*model)->GetSkeleton()->SetUpdated(false);
659 if (!(*model)->IsVisible()) { continue; }
660
661 s_SkeletonUpdater->UpdateView(
662 (*model)->GetSkeleton(),
663 *s_BillboardUpdater,
664 *s_BaseCamera);
665
666 nw::gfx::ResSkeleton resSkeleton = (*model)->GetSkeleton()->GetResSkeleton();
667 bool isModelCoordinate =
668 nw::ut::CheckFlag(resSkeleton.GetFlags(), nw::gfx::ResSkeletonData::FLAG_MODEL_COORDINATE);
669
670 (*model)->UpdateModelViewMatrixAndNormalMatrix(s_BaseCamera->ViewMatrix(), isModelCoordinate);
671 }
672 }
673
674 /*!--------------------------------------------------------------------------*
675 @brief シーンを描画します。
676 *---------------------------------------------------------------------------*/
677 void
RenderScene()678 RenderScene()
679 {
680 s_RenderContext->SetRenderTarget(s_RenderTarget);
681
682 // 描画コマンドを生成します。
683 s_CommandListSwapper->StartCommandSave();
684 NW_GL_ASSERT();
685
686 s_RenderContext->ClearBuffer(
687 GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT,
688 nw::ut::FloatColor(0.5f, 0.5f, 0.5f, 1.0f),
689 1.0f);
690
691 SkeletalModelArray::iterator modelEnd = s_SkeletalModels.end();
692 for (SkeletalModelArray::iterator model = s_SkeletalModels.begin(); model != modelEnd; ++model)
693 {
694 if ((*model)->IsVisible())
695 {
696 nw::gfx::ResMeshArray resMeshes = (*model)->GetResMeshes();
697
698 nw::gfx::ResMeshArray::iterator meshEnd = resMeshes.end();
699 for(nw::gfx::ResMeshArray::iterator mesh = resMeshes.begin();
700 mesh != meshEnd;
701 ++mesh)
702 {
703 if ((*model)->IsMeshVisible(*mesh))
704 {
705 s_MeshRenderer->RenderMesh(*mesh, *model);
706 }
707 }
708 }
709 }
710 NW_GL_ASSERT();
711
712 s_CommandListSwapper->EndCommandSave();
713
714 // 左目の描画を行います。
715 s_RenderContext->SetCameraMatrix(s_LeftCamera);
716 s_CommandListSwapper->ReuseCommand(false);
717 s_UpperSwapper->MakeTransferBufferCommand(s_RenderTarget, false);
718
719 // 右目の描画を行います。
720 s_RenderContext->SetCameraMatrix(s_RightCamera);
721 s_CommandListSwapper->ReuseCommand(false);
722 s_ExtensionSwapper->MakeTransferBufferCommand(s_RenderTarget, false);
723
724 s_CommandListSwapper->WaitDone();
725 s_CommandListSwapper->RunAsync();
726 }
727
728 /*!--------------------------------------------------------------------------*
729 @brief ディスプレイバッファをスワップして表示します。
730 *---------------------------------------------------------------------------*/
731 void
PresentBuffer()732 PresentBuffer()
733 {
734 s_UpperSwapper->ActivateBuffer();
735 s_ExtensionSwapper->ActivateBuffer();
736
737 nngxSwapBuffers(NN_GX_DISPLAY0);
738
739 glBindFramebuffer(GL_FRAMEBUFFER, 0);
740
741 NW_GL_ASSERT();
742
743 nngxWaitVSync(NN_GX_DISPLAY0);
744 }
745
746 /*!--------------------------------------------------------------------------*
747 @brief シーンをデモンストレーションします。
748 *---------------------------------------------------------------------------*/
749 void
DemoScene()750 DemoScene()
751 {
752 NW_NULL_ASSERT(s_RenderTarget);
753
754 InitializeScenes();
755
756 s_CommandListSwapper->RunAsync();
757
758 nw::demo::DebugUtility::PostInitializeScenes();
759
760 bool isContinuing = true;
761
762 while ( isContinuing )
763 {
764 nw::demo::DebugUtility::AdvanceAutoTestFrame();
765
766 nw::demo::PadFactory::GetPad()->Update();
767
768 UpdateScene();
769
770 SetEnvironment();
771
772 s_RenderContext->SetActiveCamera(s_BaseCameraIndex);
773
774 SubmitView();
775
776 RenderScene();
777
778 s_RenderContext->ResetState();
779
780 PresentBuffer();
781
782 if (nw::demo::Utility::IsTerminating())
783 {
784 isContinuing = false;
785 }
786 }
787
788 nw::demo::DebugUtility::PreTerminateScenes();
789
790 TerminateScenes();
791 }
792
793 } // namespace
794
795 /*!--------------------------------------------------------------------------*
796 @brief メイン関数です。
797 *---------------------------------------------------------------------------*/
798 void
nnMain()799 nnMain()
800 {
801 InitializeGraphicsSystem();
802
803 nw::demo::PadFactory::Initialize(&s_DeviceAllocator);
804
805 NW_DEMO_TEST_LOOP(&s_DeviceAllocator, NULL, NULL)
806 {
807 InitializeGraphics();
808
809 DemoScene();
810
811 TerminateGraphics();
812 }
813
814 nw::demo::PadFactory::Finalize();
815
816 FinalizeGraphicsSystem();
817 }
818