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