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