1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     demo_Utility.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: 25056 $
14  *---------------------------------------------------------------------------*/
15 
16 #include <nw/types.h>
17 #include <nw/os.h>
18 #include <nw/ut/ut_Inlines.h>
19 #include <nw/demo/demo_Utility.h>
20 #include <nw/gfx.h>
21 
22 #include <nn/fs.h>
23 
24 namespace nw {
25 namespace demo {
26 
27 const nw::math::VEC3 Utility::CAMERA_POSITION = nw::math::VEC3(7.0f, 3.5f, -5.0f);
28 const nw::math::VEC3 Utility::TARGET_POSITION = nw::math::VEC3(0.0f, 0.0f, 0.0f);
29 const f32 Utility::NEAR_CLIP = 0.1f;
30 const f32 Utility::FAR_CLIP = 1000.0f;
31 const f32 Utility::FOVY_RADIAN = NW_MATH_DEG_TO_RAD(37.8f);
32 const nw::math::VEC2 Utility::PROJECTION_CENTER = nw::math::VEC2(0.0f, 0.0f);
33 const f32 Utility::PROJECTION_HEIGHT = 1.0f;
34 
35 
36 //----------------------------------------
37 ResourceSet*
LoadResources(ResourceArray & resourceArray,const wchar_t * resourcePath,os::IAllocator * allocator)38 Utility::LoadResources(ResourceArray& resourceArray, const wchar_t* resourcePath, os::IAllocator* allocator)
39 {
40     ResourceSet resourceSet;
41     // 現在、デバイスメモリ上に読み込む方式にのみ対応しています。
42     // テクスチャをロードするには128byteアライメントを行う必要があります。
43     const int resourceAlignment = 128;
44     resourceSet.buffer = nw::demo::Utility::LoadFile(allocator, resourcePath, resourceAlignment);
45 
46     if (!resourceSet.buffer)
47     {
48         return NULL;
49     }
50 
51     resourceSet.resource = nw::gfx::ResGraphicsFile(&(resourceSet.buffer.front()));
52 
53     bool isPushed = resourceArray.push_back(resourceSet);
54 
55     NW_ASSERT(isPushed);
56 
57     return &(resourceArray.back());
58 }
59 
60 //----------------------------------------
61 nw::gfx::Camera*
CreateCamera(os::IAllocator * allocator,const nw::math::VEC3 & cameraPosition,const nw::math::VEC3 & targetPosition,f32 nearClip,f32 farClip,f32 fovyRadian,nw::math::PivotDirection pivotDirection,f32 wScale)62 Utility::CreateCamera(
63     os::IAllocator* allocator,
64     const nw::math::VEC3& cameraPosition,
65     const nw::math::VEC3& targetPosition,
66     f32 nearClip,
67     f32 farClip,
68     f32 fovyRadian,
69     nw::math::PivotDirection pivotDirection,
70     f32 wScale
71 )
72 {
73     NW_POINTER_ASSERT(allocator);
74 
75     nw::gfx::LookAtTargetViewUpdater* viewUpdater =
76         nw::gfx::LookAtTargetViewUpdater::Create(allocator);
77     NW_POINTER_ASSERT(viewUpdater);
78 
79     nw::gfx::ResLookAtTargetViewUpdater resViewUpdater =
80         nw::gfx::ResStaticCast<nw::gfx::ResLookAtTargetViewUpdater>(viewUpdater->GetResource());
81 
82     resViewUpdater.SetTargetPosition(targetPosition);
83     resViewUpdater.SetUpwardVector(0.0f,1.0f,0.0f);
84 
85     nw::gfx::PerspectiveProjectionUpdater* projectionUpdater =
86         nw::gfx::PerspectiveProjectionUpdater::Create(allocator);
87     NW_POINTER_ASSERT(projectionUpdater);
88 
89     projectionUpdater->SetPivotDirection(pivotDirection);
90 
91     nw::gfx::ResPerspectiveProjectionUpdater resProjectionUpdater =
92         nw::gfx::ResStaticCast<nw::gfx::ResPerspectiveProjectionUpdater>(
93         projectionUpdater->GetResource());
94     resProjectionUpdater.SetNear(nearClip);
95     resProjectionUpdater.SetFar(farClip);
96     resProjectionUpdater.SetFovy(fovyRadian);
97 
98     nw::gfx::Camera* camera =
99         nw::gfx::Camera::DynamicBuilder()
100         .MaxChildren(0)
101         .MaxCallbacks(0)
102         .ViewUpdater(viewUpdater)
103         .ProjectionUpdater(projectionUpdater)
104         .Create(allocator);
105 
106     NW_POINTER_ASSERT(camera);
107 
108     camera->Transform().SetTranslate(cameraPosition);
109     camera->SetWScale(wScale);
110 
111     return camera;
112 }
113 
114 //----------------------------------------
115 nw::gfx::Camera*
CreateAimCamera(os::IAllocator * allocator,const nw::math::VEC3 & cameraPosition,const nw::math::VEC3 & targetPosition,f32 nearClip,f32 farClip,f32 fovyRadian,nw::math::PivotDirection pivotDirection,f32 wScale)116 Utility::CreateAimCamera(
117     os::IAllocator* allocator,
118     const nw::math::VEC3& cameraPosition,
119     const nw::math::VEC3& targetPosition,
120     f32 nearClip,
121     f32 farClip,
122     f32 fovyRadian,
123     nw::math::PivotDirection pivotDirection,
124     f32 wScale
125 )
126 {
127     NW_POINTER_ASSERT(allocator);
128 
129     nw::gfx::AimTargetViewUpdater* viewUpdater =
130         nw::gfx::AimTargetViewUpdater::Create(allocator);
131     NW_POINTER_ASSERT(viewUpdater);
132 
133     nw::gfx::ResAimTargetViewUpdater resViewUpdater =
134         nw::gfx::ResStaticCast<nw::gfx::ResAimTargetViewUpdater>(viewUpdater->GetResource());
135 
136     resViewUpdater.SetTargetPosition(targetPosition);
137     resViewUpdater.SetTwist(0.0f);
138 
139     nw::gfx::PerspectiveProjectionUpdater* projectionUpdater =
140         nw::gfx::PerspectiveProjectionUpdater::Create(allocator);
141     NW_POINTER_ASSERT(projectionUpdater);
142 
143     projectionUpdater->SetPivotDirection(pivotDirection);
144 
145     nw::gfx::ResPerspectiveProjectionUpdater resProjectionUpdater =
146         nw::gfx::ResStaticCast<nw::gfx::ResPerspectiveProjectionUpdater>(
147         projectionUpdater->GetResource());
148     resProjectionUpdater.SetNear(nearClip);
149     resProjectionUpdater.SetFar(farClip);
150     resProjectionUpdater.SetFovy(fovyRadian);
151 
152     nw::gfx::Camera* camera =
153         nw::gfx::Camera::DynamicBuilder()
154         .MaxChildren(0)
155         .MaxCallbacks(0)
156         .ViewUpdater(viewUpdater)
157         .ProjectionUpdater(projectionUpdater)
158         .Create(allocator);
159 
160     NW_POINTER_ASSERT(camera);
161 
162     camera->Transform().SetTranslate(cameraPosition);
163     camera->SetWScale(wScale);
164 
165     return camera;
166 }
167 
168 //----------------------------------------
169 nw::gfx::Camera*
CreateFrustumCamera(os::IAllocator * allocator,const nw::math::VEC3 & cameraPosition,const nw::math::VEC3 & targetPosition,f32 nearClip,f32 farClip,const nw::math::VEC2 & projectionCenter,f32 projectionHeight,nw::math::PivotDirection pivotDirection,f32 wScale)170 Utility::CreateFrustumCamera(
171     os::IAllocator* allocator,
172     const nw::math::VEC3& cameraPosition,
173     const nw::math::VEC3& targetPosition,
174     f32 nearClip,
175     f32 farClip,
176     const nw::math::VEC2& projectionCenter,
177     f32 projectionHeight,
178     nw::math::PivotDirection pivotDirection,
179     f32 wScale
180 )
181 {
182     NW_POINTER_ASSERT(allocator);
183 
184     nw::gfx::LookAtTargetViewUpdater* viewUpdater =
185         nw::gfx::LookAtTargetViewUpdater::Create(allocator);
186     NW_POINTER_ASSERT(viewUpdater);
187 
188     nw::gfx::ResLookAtTargetViewUpdater resViewUpdater =
189         nw::gfx::ResStaticCast<nw::gfx::ResLookAtTargetViewUpdater>(viewUpdater->GetResource());
190 
191     resViewUpdater.SetTargetPosition(targetPosition);
192     resViewUpdater.SetUpwardVector(0.0f,1.0f,0.0f);
193 
194     nw::gfx::FrustumProjectionUpdater* projectionUpdater =
195         nw::gfx::FrustumProjectionUpdater::Create(allocator);
196     NW_POINTER_ASSERT(projectionUpdater);
197 
198     projectionUpdater->SetPivotDirection(pivotDirection);
199 
200     nw::gfx::ResFrustumProjectionUpdater resProjectionUpdater =
201         nw::gfx::ResStaticCast<nw::gfx::ResFrustumProjectionUpdater>(
202         projectionUpdater->GetResource());
203     resProjectionUpdater.SetNear(nearClip);
204     resProjectionUpdater.SetFar(farClip);
205     nw::gfx::ResProjectionRect rect = resProjectionUpdater.GetRect();
206     rect.m_Center = projectionCenter;
207     rect.m_Height = projectionHeight;
208     resProjectionUpdater.SetRect(rect);
209 
210     nw::gfx::Camera* camera =
211         nw::gfx::Camera::DynamicBuilder()
212         .MaxChildren(0)
213         .MaxCallbacks(0)
214         .ViewUpdater(viewUpdater)
215         .ProjectionUpdater(projectionUpdater)
216         .Create(allocator);
217 
218     NW_POINTER_ASSERT(camera);
219 
220     camera->Transform().SetTranslate(cameraPosition);
221     camera->SetWScale(wScale);
222 
223     return camera;
224 }
225 
226 //----------------------------------------
227 nw::gfx::Camera*
CreateOrthoCamera(os::IAllocator * allocator,const nw::math::VEC3 & cameraPosition,const nw::math::VEC3 & targetPosition,f32 nearClip,f32 farClip,const nw::math::VEC2 & projectionCenter,f32 projectionHeight,nw::math::PivotDirection pivotDirection,f32 wScale)228 Utility::CreateOrthoCamera(
229     os::IAllocator* allocator,
230     const nw::math::VEC3& cameraPosition,
231     const nw::math::VEC3& targetPosition,
232     f32 nearClip,
233     f32 farClip,
234     const nw::math::VEC2& projectionCenter,
235     f32 projectionHeight,
236     nw::math::PivotDirection pivotDirection,
237     f32 wScale
238 )
239 {
240     NW_POINTER_ASSERT(allocator);
241 
242     nw::gfx::LookAtTargetViewUpdater* viewUpdater =
243         nw::gfx::LookAtTargetViewUpdater::Create(allocator);
244     NW_POINTER_ASSERT(viewUpdater);
245 
246     nw::gfx::ResLookAtTargetViewUpdater resViewUpdater =
247         nw::gfx::ResStaticCast<nw::gfx::ResLookAtTargetViewUpdater>(viewUpdater->GetResource());
248 
249     resViewUpdater.SetTargetPosition(targetPosition);
250     resViewUpdater.SetUpwardVector(0.0f,1.0f,0.0f);
251 
252     nw::gfx::OrthoProjectionUpdater* projectionUpdater =
253         nw::gfx::OrthoProjectionUpdater::Create(allocator);
254     NW_POINTER_ASSERT(projectionUpdater);
255 
256     projectionUpdater->SetPivotDirection(pivotDirection);
257 
258     nw::gfx::ResOrthoProjectionUpdater resProjectionUpdater =
259         nw::gfx::ResStaticCast<nw::gfx::ResOrthoProjectionUpdater>(
260         projectionUpdater->GetResource());
261     resProjectionUpdater.SetNear(nearClip);
262     resProjectionUpdater.SetFar(farClip);
263     nw::gfx::ResProjectionRect rect = resProjectionUpdater.GetRect();
264     rect.m_Center = projectionCenter;
265     rect.m_Height = projectionHeight;
266     resProjectionUpdater.SetRect(rect);
267 
268     nw::gfx::Camera* camera =
269         nw::gfx::Camera::DynamicBuilder()
270         .MaxChildren(0)
271         .MaxCallbacks(0)
272         .ViewUpdater(viewUpdater)
273         .ProjectionUpdater(projectionUpdater)
274         .Create(allocator);
275 
276     NW_POINTER_ASSERT(camera);
277 
278     camera->Transform().SetTranslate(cameraPosition);
279     camera->SetWScale(wScale);
280 
281     return camera;
282 }
283 
284 //----------------------------------------
285 void
CreateStereoCameras(nw::gfx::Camera ** ppBaseCamera,nw::gfx::Camera ** ppLeftCamera,nw::gfx::Camera ** ppRightCamera,os::IAllocator * allocator,const nw::math::VEC3 & cameraPosition,const nw::math::VEC3 & targetPosition,f32 nearClip,f32 farClip,f32 fovyRadian,f32 wScale)286 Utility::CreateStereoCameras(
287     nw::gfx::Camera** ppBaseCamera,
288     nw::gfx::Camera** ppLeftCamera,
289     nw::gfx::Camera** ppRightCamera,
290     os::IAllocator* allocator,
291     const nw::math::VEC3& cameraPosition,
292     const nw::math::VEC3& targetPosition,
293     f32 nearClip,
294     f32 farClip,
295     f32 fovyRadian,
296     f32 wScale
297 )
298 {
299     NW_POINTER_ASSERT(ppBaseCamera);
300     NW_POINTER_ASSERT(ppLeftCamera);
301     NW_POINTER_ASSERT(ppRightCamera);
302     NW_POINTER_ASSERT(allocator);
303 
304     *ppBaseCamera = nw::demo::Utility::CreateCamera(
305         allocator,
306         cameraPosition,
307         targetPosition,
308         nearClip,
309         farClip,
310         fovyRadian,
311         nw::math::PIVOT_NONE
312     );
313     (*ppBaseCamera)->SetWScale(wScale);
314 
315     *ppLeftCamera =
316         nw::gfx::Camera::DynamicBuilder()
317         .MaxChildren(0)
318         .MaxCallbacks(0)
319         .Create(allocator);
320 
321     NW_POINTER_ASSERT(*ppLeftCamera);
322 
323     (*ppLeftCamera)->SetWScale(wScale);
324 
325     *ppRightCamera =
326         nw::gfx::Camera::DynamicBuilder()
327         .MaxChildren(0)
328         .MaxCallbacks(0)
329         .Create(allocator);
330 
331     NW_POINTER_ASSERT(*ppRightCamera);
332 
333     (*ppRightCamera)->SetWScale(wScale);
334 }
335 
336 
337 //----------------------------------------
338 void
SetCameraAspectRatio(nw::gfx::Camera * camera,f32 aspectRatio)339 Utility::SetCameraAspectRatio(
340     nw::gfx::Camera* camera,
341     f32 aspectRatio
342 )
343 {
344     NW_POINTER_ASSERT(camera);
345 
346     f32 fovy;
347     f32 near;
348     f32 far;
349     camera->GetPerspective(&fovy, NULL, &near, &far);
350 
351     camera->SetPerspective(fovy, aspectRatio, near, far);
352 
353     camera->UpdateCameraMatrix();
354 }
355 
356 //----------------------------------------
357 nw::gfx::IRenderTarget*
CreateUpperScreenBuffer(os::IAllocator * allocator,nw::demo::RenderSystem::Description & renderDescription)358 Utility::CreateUpperScreenBuffer(
359     os::IAllocator* allocator,
360     nw::demo::RenderSystem::Description& renderDescription
361 )
362 {
363     // オンスクリーンバッファは縦と横が逆になっているため、
364     // 幅と高さを逆に設定しています。
365     return nw::gfx::IRenderTarget::Builder()
366         .BufferSize(
367             renderDescription.upperScreenDescription.height,
368             renderDescription.upperScreenDescription.width
369         )
370         .ColorFormat(renderDescription.renderColorFormat)
371         .Create(allocator);
372 }
373 
374 //----------------------------------------
375 nw::gfx::IRenderTarget*
CreateLowerScreenBuffer(os::IAllocator * allocator,nw::demo::RenderSystem::Description & renderDescription)376 Utility::CreateLowerScreenBuffer(
377     os::IAllocator* allocator,
378     nw::demo::RenderSystem::Description& renderDescription
379 )
380 {
381     // オンスクリーンバッファは縦と横が逆になっているため、
382     // 幅と高さを逆に設定しています。
383     return nw::gfx::IRenderTarget::Builder()
384         .BufferSize(
385             renderDescription.lowerScreenDescription.height,
386             renderDescription.lowerScreenDescription.width
387         )
388         .ColorFormat(renderDescription.renderColorFormat)
389         .Create(allocator);
390 }
391 
392 //----------------------------------------
393 nw::gfx::SceneNode*
CreateSceneNode(os::IAllocator * deviceAllocator,nw::gfx::ResSceneObject resource,bool isAnimationEnabled,nw::gfx::Model::BufferOption bufferOption,s32 maxAnimObjects)394 Utility::CreateSceneNode(
395     os::IAllocator* deviceAllocator,
396     nw::gfx::ResSceneObject resource,
397     bool isAnimationEnabled,
398     nw::gfx::Model::BufferOption bufferOption,
399     s32 maxAnimObjects
400 )
401 {
402     nw::gfx::SceneObject* sceneObject = nw::gfx::SceneBuilder()
403         .Resource(resource)
404         .BufferOption(bufferOption)
405         .MaxAnimObjectsPerGroup(maxAnimObjects)
406         .IsAnimationEnabled(isAnimationEnabled)
407         .CreateObject(deviceAllocator, deviceAllocator);
408 
409     nw::gfx::SceneNode* node = nw::ut::DynamicCast<nw::gfx::SceneNode*>(sceneObject);
410 
411     return node;
412 }
413 
414 //----------------------------------------
415 ut::MoveArray<u8>
LoadFile(os::IAllocator * allocator,const wchar_t * filePath,u32 align)416 Utility::LoadFile(
417     os::IAllocator* allocator,
418     const wchar_t* filePath,
419     u32 align /* = 32 */
420 )
421 {
422     nn::fs::FileReader fileReader;
423 
424     nn::Result result = fileReader.TryInitialize(filePath);
425     if (result.IsFailure())
426     {
427         return nw::ut::MoveArray<u8>();
428     }
429     s32 fileSize = static_cast<s32>(fileReader.GetSize());
430 
431     void* memory = allocator->Alloc(fileSize, static_cast<u8>(align));
432     nw::ut::MoveArray<u8> buffer(memory, fileSize, allocator);
433     buffer.resize(fileSize);
434 
435     fileReader.Read(&buffer.front(), fileSize);
436 
437     fileReader.Finalize();
438 
439     // コンテナを返してますが、バッファはコピーされません。
440     // 所有権が移動します。
441     return buffer;
442 }
443 
444 //----------------------------------------
445 nw::gfx::AnimGroup*
GetAnimGroup(nw::gfx::SceneObject * object,AnimationType animationType)446 Utility::GetAnimGroup(
447     nw::gfx::SceneObject* object,
448     AnimationType animationType
449 )
450 {
451     // アニメーショングループを取得します。
452     nw::gfx::AnimGroup* animGroup = NULL;
453 
454     switch (animationType)
455     {
456     case SKELETAL_ANIMATION:
457         {
458             nw::gfx::SkeletalModel* skeletalModel = nw::ut::DynamicCast<nw::gfx::SkeletalModel*>(object);
459             NW_ASSERT(skeletalModel);
460             animGroup = skeletalModel->GetSkeletalAnimGroup();
461         }
462         break;
463     case MATERIAL_ANIMATION:
464         {
465             nw::gfx::Model* model = nw::ut::DynamicCast<nw::gfx::Model*>(object);
466             NW_ASSERT(model);
467             animGroup = model->GetMaterialAnimGroup();
468         }
469         break;
470     case VISIBILITY_ANIMATION:
471         {
472             nw::gfx::Model* model = nw::ut::DynamicCast<nw::gfx::Model*>(object);
473             NW_ASSERT(model);
474             animGroup = model->GetVisibilityAnimGroup();
475         }
476         break;
477     case CAMERA_ANIMATION:
478         {
479             nw::gfx::Camera* camera = nw::ut::DynamicCast<nw::gfx::Camera*>(object);
480             NW_ASSERT(camera);
481             animGroup = camera->GetAnimGroup();
482         }
483         break;
484     case LIGHT_ANIMATION:
485         {
486             nw::gfx::Light* light = nw::ut::DynamicCast<nw::gfx::Light*>(object);
487             NW_ASSERT(light);
488             animGroup = light->GetAnimGroup();
489         }
490         break;
491     default:
492         NW_FATAL_ERROR("Invalid animation type");
493     }
494 
495     return animGroup;
496 }
497 
498 //----------------------------------------
499 bool
BindAnimationObject(nw::gfx::SceneObject * object,nw::gfx::AnimObject * animObject,AnimationType animationType)500 Utility::BindAnimationObject(
501     nw::gfx::SceneObject* object,
502     nw::gfx::AnimObject* animObject,
503     AnimationType animationType
504 )
505 {
506     nw::gfx::AnimGroup* animGroup = GetAnimGroup(object, animationType);
507     if (!animGroup)
508     {
509         return false;
510     }
511 
512     if (animObject->TryBind( animGroup ).IsFailure())
513     {
514         return false;
515     }
516 
517     switch (animationType)
518     {
519     case SKELETAL_ANIMATION:
520         {
521             nw::gfx::SkeletalModel* skeletalModel = nw::ut::DynamicCast<nw::gfx::SkeletalModel*>(object);
522             NW_ASSERT(skeletalModel);
523             skeletalModel->SetSkeletalAnimObject(animObject);
524         }
525         break;
526     case MATERIAL_ANIMATION:
527         {
528             nw::gfx::Model* model = nw::ut::DynamicCast<nw::gfx::Model*>(object);
529             NW_ASSERT(model);
530             model->SetMaterialAnimObject(animObject);
531         }
532         break;
533     case VISIBILITY_ANIMATION:
534         {
535             nw::gfx::Model* model = nw::ut::DynamicCast<nw::gfx::Model*>(object);
536             NW_ASSERT(model);
537             model->SetVisibilityAnimObject(animObject);
538         }
539         break;
540     case CAMERA_ANIMATION:
541         {
542             nw::gfx::Camera* camera = nw::ut::DynamicCast<nw::gfx::Camera*>(object);
543             NW_ASSERT(camera);
544             camera->SetAnimObject(animObject);
545         }
546         break;
547     case LIGHT_ANIMATION:
548         {
549             nw::gfx::Light* light = nw::ut::DynamicCast<nw::gfx::Light*>(object);
550             NW_ASSERT(light);
551             light->SetAnimObject(animObject);
552         }
553         break;
554     default:
555         NW_FATAL_ERROR("Invalid animation type");
556     }
557 
558     return true;
559 }
560 
561 
562 namespace internal {
563 
564 //----------------------------------------
565 bool
IsTerminatingImpl()566 IsTerminatingImpl()
567 {
568     return false;
569 }
570 
571 } // namespace internal
572 
573 } /* namespace demo */
574 } /* namespace nw   */
575