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     s_GraphicsMemoryAllocator.Finalize();
284 
285     NW_GL_ASSERT();
286 }
287 
288 /*!--------------------------------------------------------------------------*
289   @brief        グラフィックスリソースをロードします。
290 
291   @param[in]    resourcePath ファイルのパス名
292 
293   @return       ロードしたグラフィックス情報を返します。
294  *---------------------------------------------------------------------------*/
295 ResourceSet*
LoadResources(const wchar_t * resourcePath)296 LoadResources(const wchar_t* resourcePath)
297 {
298     ResourceSet resourceSet;
299     // 現在、デバイスメモリ上に読み込む方式にのみ対応しています。
300     // テクスチャをロードするには128byteアライメントを行う必要があります。
301     static const int resourceAlignment = 128;
302     resourceSet.buffer = nw::demo::Utility::LoadFile(&s_DeviceAllocator , resourcePath, resourceAlignment);
303 
304     if (!resourceSet.buffer)
305     {
306         return NULL;
307     }
308 
309     resourceSet.resource = nw::gfx::ResGraphicsFile(&(resourceSet.buffer.front()));
310 
311     bool isPushed = s_Resources.push_back(resourceSet);
312 
313     NW_ASSERT(isPushed);
314 
315     return &(s_Resources.back());
316 }
317 
318 /*!--------------------------------------------------------------------------*
319   @brief        シーンノードを生成します。
320 
321   @param[in]    resource シーンノードのリソースです。
322 
323   @return       生成したシーンノードです。。
324  *---------------------------------------------------------------------------*/
325 nw::gfx::SceneNode*
CreateSceneNode(nw::gfx::ResSceneObject resource)326 CreateSceneNode(nw::gfx::ResSceneObject resource)
327 {
328     nw::gfx::SceneObject* sceneObject = nw::gfx::SceneBuilder()
329         .Resource(resource)
330         .MaxChildren(0)
331         .CreateObject(&s_DeviceAllocator, &s_DeviceAllocator);
332 
333     return nw::ut::DynamicCast<nw::gfx::SceneNode*>(sceneObject);
334 }
335 
336 /*!--------------------------------------------------------------------------*
337   @brief        リソース関連の構築をします。
338 *---------------------------------------------------------------------------*/
339 void
BuildResources(ResourceSet * resourceSet)340 BuildResources(ResourceSet* resourceSet)
341 {
342     resourceSet->resource.ForeachTexture(nw::gfx::LocationFlagSetter(NN_GX_MEM_VRAMA | GL_NO_COPY_FCRAM_DMP));
343     resourceSet->resource.ForeachIndexStream(nw::gfx::LocationFlagSetter(NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP));
344     resourceSet->resource.ForeachVertexStream(nw::gfx::LocationFlagSetter(NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP));
345 
346     nw::gfx::Result result = resourceSet->resource.Setup(&s_DeviceAllocator);
347     if (result.IsFailure())
348     {
349         NW_FATAL_ERROR("Fail to set up model. A result code is 0x%x", result.GetCode());
350     }
351 
352     nw::gfx::ResModelArray models = resourceSet->resource.GetModels();
353     nw::gfx::ResModelArray::iterator modelsEnd = models.end();
354     for (nw::gfx::ResModelArray::iterator modelResource = models.begin();
355         modelResource != modelsEnd; ++modelResource)
356     {
357         nw::gfx::SceneNode* node = CreateSceneNode(*modelResource);
358         NW_NULL_ASSERT(node);
359         NW_ASSERT(nw::ut::IsTypeOf<nw::gfx::SkeletalModel>(node));
360 
361         s_SkeletalModels.push_back(static_cast<nw::gfx::SkeletalModel*>(node));
362     }
363 
364     nw::gfx::ResLightArray lights = resourceSet->resource.GetLights();
365     for (nw::gfx::ResLightArray::iterator lightResource = lights.begin();
366         lightResource != lights.end(); ++lightResource)
367     {
368         nw::gfx::SceneNode* node = CreateSceneNode(*lightResource);
369         NW_NULL_ASSERT(node);
370         NW_ASSERT(nw::ut::IsTypeOf<nw::gfx::FragmentLight>(node));
371 
372         s_FragmentLights.push_back(static_cast<nw::gfx::FragmentLight*>(node));
373     }
374 }
375 
376 /*!--------------------------------------------------------------------------*
377   @brief        カメラの構築をします。
378 *---------------------------------------------------------------------------*/
379 void
BuildCameras()380 BuildCameras()
381 {
382     nw::gfx::LookAtTargetViewUpdater* viewUpdater
383         = nw::gfx::LookAtTargetViewUpdater::Create(&s_DeviceAllocator);
384 
385     nw::gfx::ResLookAtTargetViewUpdater resViewUpdater =
386         nw::gfx::ResStaticCast<nw::gfx::ResLookAtTargetViewUpdater>(
387             viewUpdater->GetResource());
388     resViewUpdater.SetTargetPosition(0.0f,10.0f,0.0f);
389     resViewUpdater.SetUpwardVector(0.0f,1.0f,0.0f);
390 
391     nw::gfx::PerspectiveProjectionUpdater* projectionUpdater
392         = nw::gfx::PerspectiveProjectionUpdater::Create(&s_DeviceAllocator);
393 
394     nw::gfx::ResPerspectiveProjectionUpdater resProjectionUpdater =
395         nw::gfx::ResStaticCast<nw::gfx::ResPerspectiveProjectionUpdater>(
396             projectionUpdater->GetResource());
397     resProjectionUpdater.SetNear(s_NearPlane);
398     resProjectionUpdater.SetFar(1000.0f);
399     resProjectionUpdater.SetFovy(NW_MATH_DEG_TO_RAD(37.8f));
400 
401     resProjectionUpdater.SetAspectRatio(
402         static_cast<f32>(s_RenderTarget->GetDescription().height) /
403             static_cast<f32>(s_RenderTarget->GetDescription().width));
404 
405     s_BaseCamera =
406         nw::gfx::Camera::DynamicBuilder()
407         .MaxChildren(0)
408         .MaxCallbacks(0)
409         .ViewUpdater(viewUpdater)
410         .ProjectionUpdater(projectionUpdater)
411         .Create(&s_DeviceAllocator);
412     NW_POINTER_ASSERT(s_BaseCamera);
413     s_BaseCamera->Transform().SetTranslate(nw::math::VEC3(20.0f, 15.0f, 20.0f));
414 
415     s_LeftCamera =
416         nw::gfx::Camera::DynamicBuilder()
417         .MaxChildren(0)
418         .MaxCallbacks(0)
419         .Create(&s_DeviceAllocator);
420     NW_POINTER_ASSERT(s_LeftCamera);
421 
422     s_RightCamera =
423         nw::gfx::Camera::DynamicBuilder()
424         .MaxChildren(0)
425         .MaxCallbacks(0)
426         .Create(&s_DeviceAllocator);
427     NW_POINTER_ASSERT(s_RightCamera);
428 
429     s_CameraController =
430         nw::demo::CameraController::Builder()
431         .MaxCameraCount(1)
432         .Create(&s_DeviceAllocator);
433     s_CameraController->Register(s_BaseCamera);
434 }
435 
436 /*!--------------------------------------------------------------------------*
437   @brief        アニメーション関連の構築をします。
438  *---------------------------------------------------------------------------*/
439 void
BuildAnimations()440 BuildAnimations()
441 {
442     s_AnimObject = nw::demo::Utility::BindAnimationByName(
443         &s_DeviceAllocator,
444         s_SkeletalModels,
445         s_ResAnims,
446         "Male",
447         "Walk",
448         nw::demo::Utility::SKELETAL_ANIMATION,
449         false);
450 }
451 
452 /*!--------------------------------------------------------------------------*
453   @brief        シーンを初期化します。
454 *---------------------------------------------------------------------------*/
455 void
InitializeScenes()456 InitializeScenes()
457 {
458     BuildCameras();
459 
460     NW_FOREACH(const wchar_t* name, MODEL_RESOURCE_FILES)
461     {
462         ResourceSet* resourceSet = LoadResources(name);
463         BuildResources(resourceSet);
464         s_ResAnims.push_back(resourceSet->resource);
465     }
466 
467     NW_GL_ASSERT();
468 
469     BuildAnimations();
470 
471     s_FrameCount = 0;
472 }
473 
474 /*!--------------------------------------------------------------------------*
475   @brief        シーン関連の後始末をします。
476 *---------------------------------------------------------------------------*/
477 void
TerminateScenes()478 TerminateScenes()
479 {
480     nw::gfx::SafeDestroyAll(s_FragmentLights);
481     nw::gfx::SafeDestroyAll(s_SkeletalModels);
482     nw::demo::SafeCleanupResources(s_Resources);
483     nw::gfx::SafeDestroy(s_BaseCamera);
484     nw::gfx::SafeDestroy(s_LeftCamera);
485     nw::gfx::SafeDestroy(s_RightCamera);
486     nw::gfx::SafeDestroy(s_CameraController);
487     nw::gfx::SafeDestroy(s_AnimObject);
488 
489     NW_GL_ASSERT();
490 
491     s_Resources.clear();
492     s_ResAnims.clear();
493 }
494 
495 /*!--------------------------------------------------------------------------*
496   @brief        ノードを更新します。
497  *---------------------------------------------------------------------------*/
498 void
UpdateNode(nw::gfx::TransformNode * node)499 UpdateNode(nw::gfx::TransformNode* node)
500 {
501     // 一度計算したら計算処理をスキップする。
502     // ただし、ツリー構造は正しく解釈されない。
503     if (node->Transform().IsEnabledFlags(nw::gfx::CalculatedTransform::FLAG_IS_DIRTY))
504     {
505         s_WorldMatrixUpdater->UpdateBasic(
506             &node->WorldMatrix(),
507             &node->WorldTransform(),
508             node->Transform(),
509             nw::gfx::CalculatedTransform::Identity(),
510             nw::gfx::CalculatedTransform::Identity());
511 
512         node->Transform().DisableFlags(nw::gfx::CalculatedTransform::FLAG_IS_DIRTY);
513     }
514 }
515 
516 /*!--------------------------------------------------------------------------*
517   @brief        カメラを更新します。
518  *---------------------------------------------------------------------------*/
UpdateCamera()519 void UpdateCamera()
520 {
521     s_CameraController->Update();
522     UpdateNode(s_BaseCamera);
523     s_BaseCamera->UpdateCameraMatrix();
524 
525     // ステレオカメラの計算
526     NW_NULL_ASSERT(s_LeftCamera);
527     NW_NULL_ASSERT(s_RightCamera);
528     NW_NULL_ASSERT(s_BaseCamera);
529     nn::math::MTX44& projOriginal = s_BaseCamera->ProjectionMatrix();
530     nn::math::MTX34& viewOriginal = s_BaseCamera->ViewMatrix();
531     nn::math::MTX44& projL = s_LeftCamera->ProjectionMatrix();
532     nn::math::MTX34& viewL = s_LeftCamera->ViewMatrix();
533     nn::math::MTX44& projR = s_RightCamera->ProjectionMatrix();
534     nn::math::MTX34& viewR = s_RightCamera->ViewMatrix();
535 
536     // Ortho カメラでは別の処理を行う必要があります。
537     // 例として demo::RenderSystem::CalcStereoCamera() を参照してください。
538     const f32 DEPTH_LEVEL = 5.0f + s_NearPlane;
539     const f32 DEPTH_RANGE = 1.0f;
540     s_StereoCamera->CalculateMatrices(
541         &projL,
542         &viewL,
543         &projR,
544         &viewR,
545         &projOriginal,
546         &viewOriginal,
547         DEPTH_LEVEL,
548         DEPTH_RANGE,
549         false);
550 }
551 
552 /*!--------------------------------------------------------------------------*
553   @brief        生成されたノードを更新します。
554  *---------------------------------------------------------------------------*/
UpdateNodes()555 void UpdateNodes()
556 {
557     // フラグメントライト更新
558     FragmentLightArray::iterator lightEnd = s_FragmentLights.end();
559     for (FragmentLightArray::iterator light = s_FragmentLights.begin(); light != lightEnd; ++light)
560     {
561         UpdateNode(*light);
562     }
563 
564 
565     // スケルタルモデル更新
566     SkeletalModelArray::iterator skeletalModelEnd = s_SkeletalModels.end();
567     for (SkeletalModelArray::iterator model = s_SkeletalModels.begin(); model != skeletalModelEnd; ++model)
568     {
569         UpdateNode(*model);
570 
571         // フルベイクアニメを使用する場合は処理をスキップします。
572         if ((*model)->GetFullBakedAnimEnabled()) { continue; }
573 
574         // スケルトンが既に更新済みの場合は処理をスキップします。
575         if ((*model)->GetSkeleton()->IsUpdated()) { continue; }
576 
577         // スケルトンを更新します。
578         s_SkeletonUpdater->UpdateWorld((*model)->GetSkeleton(), *s_WorldMatrixUpdater);
579 
580         // スケルトンが更新済みであることを表すフラグを true にします。
581         (*model)->GetSkeleton()->SetUpdated(true);
582     }
583 }
584 
585 /*!--------------------------------------------------------------------------*
586   @brief        アニメーションを評価します。
587  *---------------------------------------------------------------------------*/
588 void
EvaluateSkeletalAnim()589 EvaluateSkeletalAnim()
590 {
591     SkeletalModelArray::iterator skeletalModelEnd = s_SkeletalModels.end();
592     for (SkeletalModelArray::iterator model = s_SkeletalModels.begin(); model != skeletalModelEnd; ++model)
593     {
594         (*model)->GetAnimBinding()->Evaluate(nw::anim::ResGraphicsAnimGroup::EVALUATION_BEFORE_WORLD_UPDATE);
595         (*model)->GetAnimBinding()->Evaluate(nw::anim::ResGraphicsAnimGroup::EVALUATION_AFTER_SCENE_CULLING);
596     }
597 }
598 
599 /*!--------------------------------------------------------------------------*
600   @brief        アニメーションのフレームを更新します。
601  *---------------------------------------------------------------------------*/
602 void
UpdateFrame()603 UpdateFrame()
604 {
605     SkeletalModelArray::iterator skeletalModelEnd = s_SkeletalModels.end();
606     for (SkeletalModelArray::iterator model = s_SkeletalModels.begin(); model != skeletalModelEnd; ++model)
607     {
608         (*model)->UpdateFrame();
609     }
610 }
611 
612 /*!--------------------------------------------------------------------------*
613   @brief        シーンを更新します。
614  *---------------------------------------------------------------------------*/
615 void
UpdateScene()616 UpdateScene()
617 {
618     EvaluateSkeletalAnim();
619 
620     UpdateNodes();
621 
622     UpdateFrame();
623 
624     UpdateCamera();
625 
626     ++s_FrameCount;
627 }
628 
629 /*!--------------------------------------------------------------------------*
630   @brief        カメラ、ライト、フォグなどのシーン環境を設定します。
631  *---------------------------------------------------------------------------*/
632 void
SetEnvironment()633 SetEnvironment()
634 {
635     nw::gfx::SceneEnvironment& sceneEnvironment = s_RenderContext->GetSceneEnvironment();
636     sceneEnvironment.SetCamera(s_BaseCameraIndex, s_BaseCamera);
637 
638     //-----------------------------
639     FragmentLightArray::iterator lightEnd = s_FragmentLights.end();
640     for (FragmentLightArray::iterator light = s_FragmentLights.begin(); light != lightEnd; ++light)
641     {
642         sceneEnvironment.SetFragmentLight(*light);
643     }
644 }
645 
646 /*!--------------------------------------------------------------------------*
647   @brief        ビューに関連する更新処理を行います。
648  *---------------------------------------------------------------------------*/
649 void
SubmitView()650 SubmitView()
651 {
652     SkeletalModelArray::iterator skeletalModelEnd = s_SkeletalModels.end();
653     for (SkeletalModelArray::iterator model = s_SkeletalModels.begin(); model != skeletalModelEnd; ++model)
654     {
655         // スケルトンが更新済みであることを表すフラグを false に戻します。
656         (*model)->GetSkeleton()->SetUpdated(false);
657         if (!(*model)->IsVisible()) { continue; }
658 
659         s_SkeletonUpdater->UpdateView(
660             (*model)->GetSkeleton(),
661             *s_BillboardUpdater,
662             *s_BaseCamera);
663 
664         nw::gfx::ResSkeleton resSkeleton = (*model)->GetSkeleton()->GetResSkeleton();
665         bool isModelCoordinate =
666             nw::ut::CheckFlag(resSkeleton.GetFlags(), nw::gfx::ResSkeletonData::FLAG_MODEL_COORDINATE);
667 
668         (*model)->UpdateModelViewMatrixAndNormalMatrix(s_BaseCamera->ViewMatrix(), isModelCoordinate);
669     }
670 }
671 
672 /*!--------------------------------------------------------------------------*
673   @brief        シーンを描画します。
674  *---------------------------------------------------------------------------*/
675 void
RenderScene()676 RenderScene()
677 {
678     s_RenderContext->SetRenderTarget(s_RenderTarget);
679 
680     // 描画コマンドを生成します。
681     s_CommandListSwapper->StartCommandSave();
682     NW_GL_ASSERT();
683 
684     s_RenderContext->ClearBuffer(
685         GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT,
686         nw::ut::FloatColor(0.5f, 0.5f, 0.5f, 1.0f),
687         1.0f);
688 
689     SkeletalModelArray::iterator modelEnd = s_SkeletalModels.end();
690     for (SkeletalModelArray::iterator model = s_SkeletalModels.begin(); model != modelEnd; ++model)
691     {
692         if ((*model)->IsVisible())
693         {
694             nw::gfx::ResMeshArray resMeshes = (*model)->GetResMeshes();
695 
696             nw::gfx::ResMeshArray::iterator meshEnd = resMeshes.end();
697             for(nw::gfx::ResMeshArray::iterator mesh = resMeshes.begin();
698                 mesh != meshEnd;
699                 ++mesh)
700             {
701                 if ((*model)->IsMeshVisible(*mesh))
702                 {
703                     s_MeshRenderer->RenderMesh(*mesh, *model);
704                 }
705             }
706         }
707     }
708     NW_GL_ASSERT();
709 
710     s_CommandListSwapper->EndCommandSave();
711 
712     // 左目の描画を行います。
713     s_RenderContext->SetCameraMatrix(s_LeftCamera);
714     s_CommandListSwapper->ReuseCommand(false);
715     s_UpperSwapper->MakeTransferBufferCommand(s_RenderTarget, false);
716 
717     // 右目の描画を行います。
718     s_RenderContext->SetCameraMatrix(s_RightCamera);
719     s_CommandListSwapper->ReuseCommand(false);
720     s_ExtensionSwapper->MakeTransferBufferCommand(s_RenderTarget, false);
721 
722     s_CommandListSwapper->WaitDone();
723     s_CommandListSwapper->RunAsync();
724 }
725 
726 /*!--------------------------------------------------------------------------*
727   @brief        ディスプレイバッファをスワップして表示します。
728  *---------------------------------------------------------------------------*/
729 void
PresentBuffer()730 PresentBuffer()
731 {
732     s_UpperSwapper->ActivateBuffer();
733     s_ExtensionSwapper->ActivateBuffer();
734 
735     nngxSwapBuffers(NN_GX_DISPLAY0);
736 
737     glBindFramebuffer(GL_FRAMEBUFFER, 0);
738 
739     NW_GL_ASSERT();
740 
741     nngxWaitVSync(NN_GX_DISPLAY0);
742 }
743 
744 /*!--------------------------------------------------------------------------*
745   @brief        シーンをデモンストレーションします。
746  *---------------------------------------------------------------------------*/
747 void
DemoScene()748 DemoScene()
749 {
750     NW_NULL_ASSERT(s_RenderTarget);
751 
752     InitializeScenes();
753 
754     s_CommandListSwapper->RunAsync();
755 
756     nw::demo::DebugUtility::PostInitializeScenes();
757 
758     bool isContinuing = true;
759 
760     while ( isContinuing )
761     {
762         nw::demo::DebugUtility::AdvanceAutoTestFrame();
763 
764         nw::demo::PadFactory::GetPad()->Update();
765 
766         UpdateScene();
767 
768         SetEnvironment();
769 
770         s_RenderContext->SetActiveCamera(s_BaseCameraIndex);
771 
772         SubmitView();
773 
774         RenderScene();
775 
776         s_RenderContext->ResetState();
777 
778         PresentBuffer();
779 
780         if (nw::demo::Utility::IsTerminating())
781         {
782             isContinuing = false;
783         }
784     }
785 
786     nw::demo::DebugUtility::PreTerminateScenes();
787 
788     TerminateScenes();
789 }
790 
791 } // namespace
792 
793 /*!--------------------------------------------------------------------------*
794   @brief        メイン関数です。
795  *---------------------------------------------------------------------------*/
796 void
nnMain()797 nnMain()
798 {
799     InitializeGraphicsSystem();
800 
801     nw::demo::PadFactory::Initialize(&s_DeviceAllocator);
802 
803     NW_DEMO_TEST_LOOP(&s_DeviceAllocator, NULL, NULL)
804     {
805         InitializeGraphics();
806 
807         DemoScene();
808 
809         TerminateGraphics();
810     }
811 
812     nw::demo::PadFactory::Finalize();
813 
814     FinalizeGraphicsSystem();
815 }
816