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