1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     demo_Utility.h
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: 25151 $
14  *---------------------------------------------------------------------------*/
15 
16 #ifndef NW_DEMO_UTILITY_H_
17 #define NW_DEMO_UTILITY_H_
18 
19 #include <nw/types.h>
20 #include <nw/ut/ut_MoveArray.h>
21 #include <nw/demo/demo_GraphicsDrawing.h>
22 #include <nw/demo/demo_GraphicsSystem.h>
23 #include <nw/demo/demo_Pad.h>
24 
25 // ファイル名定義ユーティリティマクロです。
26 #define NW_DEMO_FILE_PATH(name) (L"rom:/" name)
27 
28 
29 namespace nw
30 {
31 
32 namespace demo
33 {
34 
35 namespace internal
36 {
37     bool IsTerminatingImpl();
38 } // namespace internal
39 
40 //============================================================================
41 //! @name ユーティリティ
42 //@{
43 
44 //---------------------------------------------------------------------------
45 //! @brief        デモに使用するユーティリティ関数をまとめたクラスです。
46 //---------------------------------------------------------------------------
47 class Utility
48 {
49 public:
50     static const nw::math::VEC3 CAMERA_POSITION; //!< カメラ位置のデフォルト値です。
51     static const nw::math::VEC3 TARGET_POSITION; //!< カメラターゲットのデフォルト値です。
52     static const f32 NEAR_CLIP; //!< ニアクリップのデフォルト値です。
53     static const f32 FAR_CLIP; //!< ファークリップのデフォルト値です。
54     static const f32 FOVY_RADIAN; //!< FOVのY方向のデフォルト値です。
55     static const nw::math::VEC2 PROJECTION_CENTER; //!< カメラの投影面の中心位置です。
56     static const f32 PROJECTION_HEIGHT; //!< カメラの投影面の高さです。
57 
58     //---------------------------------------------------------------------------
59     //! @brief        アニメーションの種類を表します。
60     //---------------------------------------------------------------------------
61     enum AnimationType {
62         SKELETAL_ANIMATION,       //!< スケルタルアニメーションを表します。
63         MATERIAL_ANIMATION,       //!< マテリアルアニメーションを表します。
64         VISIBILITY_ANIMATION,     //!< ビジビリティアニメーションを表します。
65         CAMERA_ANIMATION,         //!< カメラアニメーションを表します。
66         LIGHT_ANIMATION           //!< ライトアニメーションを表します。
67     };
68 
69     //=====================
70     //! @name ファイル
71     //@{
72 
73     //---------------------------------------------------------------------------
74     //! @brief        ファイルをロードします。
75     //!
76     //! @param[in]    allocator   アロケータです。
77     //! @param[in]    filePath    ファイルのパス名です。
78     //! @param[in]    align       アライメントです。
79     //!
80     //! @return       ロードしたファイルのバッファを返します。
81     //---------------------------------------------------------------------------
82     static ut::MoveArray<u8> LoadFile(
83         os::IAllocator* allocator,
84         const wchar_t* filePath,
85         u32 align = 32
86     );
87 
88     //---------------------------------------------------------------------------
89     //! @brief        グラフィックスリソースをロードします。
90     //!
91     //! @param[in]    resourceArray 追加を行うリソースの配列です。
92     //! @param[in]    resourcePath ファイルのパス名
93     //! @param[in]    allocator アロケータです。
94     //!
95     //! @return       ロードしたグラフィックス情報を返します。
96     //---------------------------------------------------------------------------
97     static ResourceSet*
98     LoadResources(ResourceArray& resourceArray, const wchar_t* resourcePath, os::IAllocator* allocator);
99 
100     //@}
101 
102     //=====================
103     //! @name カメラ
104     //@{
105 
106     //---------------------------------------------------------------------------
107     //! @brief        カメラを生成します。
108     //!
109     //! @param[in]    allocator 生成に使用するアロケーターです。
110     //! @param[in]    cameraPosition カメラの位置座標です。
111     //! @param[in]    targetPosition カメラターゲットの座標です。
112     //! @param[in]    nearClip ニアクリップの値です。
113     //! @param[in]    farClip ファークリップの値です。
114     //! @param[in]    fovyRadian FOVのY方向の値です。
115     //! @param[in]    pivotDirection 画面の上方向です。
116     //! @param[in]    wScale wScale の値です。
117     //!
118     //! @return       生成したカメラを返します。
119     //---------------------------------------------------------------------------
120     static nw::gfx::Camera* CreateCamera(
121         os::IAllocator* allocator,
122         const nw::math::VEC3& cameraPosition = CAMERA_POSITION,
123         const nw::math::VEC3& targetPosition = TARGET_POSITION,
124         f32 nearClip = NEAR_CLIP,
125         f32 farClip = FAR_CLIP,
126         f32 fovyRadian = FOVY_RADIAN,
127         nw::math::PivotDirection pivotDirection = nw::math::PIVOT_UPSIDE_TO_TOP,
128         f32 wScale = 0.0f
129     );
130 
131     //---------------------------------------------------------------------------
132     //! @brief        カメラを生成します。
133     //!
134     //! @param[in]    allocator 生成に使用するアロケーターです。
135     //! @param[in]    cameraPosition カメラの位置座標です。
136     //! @param[in]    targetPosition カメラターゲットの座標です。
137     //! @param[in]    nearClip ニアクリップの値です。
138     //! @param[in]    farClip ファークリップの値です。
139     //! @param[in]    fovyRadian FOVのY方向の値です。
140     //! @param[in]    pivotDirection 画面の上方向です。
141     //! @param[in]    wScale wScale の値です。
142     //!
143     //! @return       生成したカメラを返します。
144     //---------------------------------------------------------------------------
145     static nw::gfx::Camera* CreateAimCamera(
146         os::IAllocator* allocator,
147         const nw::math::VEC3& cameraPosition = CAMERA_POSITION,
148         const nw::math::VEC3& targetPosition = TARGET_POSITION,
149         f32 nearClip = NEAR_CLIP,
150         f32 farClip = FAR_CLIP,
151         f32 fovyRadian = FOVY_RADIAN,
152         nw::math::PivotDirection pivotDirection = nw::math::PIVOT_UPSIDE_TO_TOP,
153         f32 wScale = 0.0f
154     );
155 
156     //---------------------------------------------------------------------------
157     //! @brief        カメラを生成します。
158     //!
159     //! @param[in]    allocator 生成に使用するアロケーターです。
160     //! @param[in]    cameraPosition カメラの位置座標です。
161     //! @param[in]    targetPosition カメラターゲットの座標です。
162     //! @param[in]    nearClip ニアクリップの値です。
163     //! @param[in]    farClip ファークリップの値です。
164     //! @param[in]    projectionCenter 投影面の中心位置です。
165     //! @param[in]    projectionHeight 投影面の高さです。
166     //! @param[in]    pivotDirection 画面の上方向です。
167     //! @param[in]    wScale wScale の値です。
168     //!
169     //! @return       生成したカメラを返します。
170     //---------------------------------------------------------------------------
171     static nw::gfx::Camera* CreateFrustumCamera(
172         os::IAllocator* allocator,
173         const nw::math::VEC3& cameraPosition = CAMERA_POSITION,
174         const nw::math::VEC3& targetPosition = TARGET_POSITION,
175         f32 nearClip = NEAR_CLIP,
176         f32 farClip = FAR_CLIP,
177         const nw::math::VEC2& projectionCenter = PROJECTION_CENTER,
178         f32 projectionHeight = PROJECTION_HEIGHT,
179         nw::math::PivotDirection pivotDirection = nw::math::PIVOT_UPSIDE_TO_TOP,
180         f32 wScale = 0.0f
181     );
182 
183     //---------------------------------------------------------------------------
184     //! @brief        カメラを生成します。
185     //!
186     //! @param[in]    allocator 生成に使用するアロケーターです。
187     //! @param[in]    cameraPosition カメラの位置座標です。
188     //! @param[in]    targetPosition カメラターゲットの座標です。
189     //! @param[in]    nearClip ニアクリップの値です。
190     //! @param[in]    farClip ファークリップの値です。
191     //! @param[in]    projectionCenter 投影面の中心位置です。
192     //! @param[in]    projectionHeight 投影面の高さです。
193     //! @param[in]    pivotDirection 画面の上方向です。
194     //! @param[in]    wScale wScale の値です。
195     //!
196     //! @return       生成したカメラを返します。
197     //---------------------------------------------------------------------------
198     static nw::gfx::Camera* CreateOrthoCamera(
199         os::IAllocator* allocator,
200         const nw::math::VEC3& cameraPosition = CAMERA_POSITION,
201         const nw::math::VEC3& targetPosition = TARGET_POSITION,
202         f32 nearClip = NEAR_CLIP,
203         f32 farClip = FAR_CLIP,
204         const nw::math::VEC2& projectionCenter = PROJECTION_CENTER,
205         f32 projectionHeight = PROJECTION_HEIGHT,
206         nw::math::PivotDirection pivotDirection = nw::math::PIVOT_UPSIDE_TO_TOP,
207         f32 wScale = 0.0f
208     );
209 
210 
211 
212     // TODO: 「ベースカメラ」という表現が適切かどうかを確認する。
213     //---------------------------------------------------------------------------
214     //! @brief        立体視に使用するベースカメラと左右カメラを生成します。
215     //!
216     //!               実際は右目用カメラと左目用カメラの区別はありません。
217     //!
218     //! @param[out]   ppBaseCamera 生成したベースカメラを返すためのポインタです。
219     //! @param[out]   ppLeftCamera 生成した右目用カメラを返すためのポインタです。
220     //! @param[out]   ppRightCamera 生成した左目用カメラを返すためのポインタです。
221     //! @param[in]    allocator 生成に使用するアロケーターです。
222     //! @param[in]    cameraPosition カメラの位置座標です。
223     //! @param[in]    targetPosition カメラターゲットの座標です。
224     //! @param[in]    nearClip ニアクリップの値です。
225     //! @param[in]    farClip ファークリップの値です。
226     //! @param[in]    fovyRadian FOVのY方向の値です。
227     //! @param[in]    wScale wScale の値です。
228     //---------------------------------------------------------------------------
229     static void CreateStereoCameras(
230         nw::gfx::Camera** ppBaseCamera,
231         nw::gfx::Camera** ppLeftCamera,
232         nw::gfx::Camera** ppRightCamera,
233         os::IAllocator* allocator,
234         const nw::math::VEC3& cameraPosition = CAMERA_POSITION,
235         const nw::math::VEC3& targetPosition = TARGET_POSITION,
236         f32 nearClip = NEAR_CLIP,
237         f32 farClip = FAR_CLIP,
238         f32 fovyRadian = FOVY_RADIAN,
239         f32 wScale = 0.0f
240     );
241 
242     //---------------------------------------------------------------------------
243     //! @brief        カメラのアスペクト比を設定します。
244     //!
245     //!               指定したレンダーターゲットに合うように設定されます。
246     //!               カメラがアタッチされているシーンを更新してから実行する必要があります。
247     //!
248     //! @param[in]    camera 設定するカメラです。
249     //! @param[in]    renderTarget アスペクト比を合わせるレンダーターゲットです。
250     //---------------------------------------------------------------------------
SetCameraAspectRatio(nw::gfx::Camera * camera,const nw::gfx::IRenderTarget * renderTarget)251     static void SetCameraAspectRatio(
252         nw::gfx::Camera* camera,
253         const nw::gfx::IRenderTarget* renderTarget
254     )
255     {
256         NW_POINTER_ASSERT(renderTarget);
257         // オンスクリーンバッファは縦と横が逆になっているため、
258         // 幅と高さを逆にしてアスペクト比を求めています。
259         SetCameraAspectRatio(
260             camera,
261             static_cast<f32>(renderTarget->GetDescription().height) /
262                 static_cast<f32>(renderTarget->GetDescription().width)
263         );
264     }
265 
266     //---------------------------------------------------------------------------
267     //! @brief        カメラのアスペクト比を設定します。
268     //!
269     //!               カメラがアタッチされているシーンを更新してから実行する必要があります。
270     //!
271     //! @param[in]    camera 設定するカメラです。
272     //! @param[in]    aspectRatio アスペクト比です。
273     //---------------------------------------------------------------------------
274     static void SetCameraAspectRatio(
275         nw::gfx::Camera* camera,
276         f32 aspectRatio
277     );
278 
279     //@}
280 
281     //=====================
282     //! @name スクリーンバッファの生成
283     //@{
284 
285 
286     //---------------------------------------------------------------------------
287     //! @brief        上画面用のスクリーンバッファを生成します。
288     //!
289     //!               レンダーシステムの設定をもとにバッファサイズなどが決定されます。
290     //!
291     //! @param[in]    allocator 生成に使用するアロケーターです。
292     //! @param[in]    renderDescription レンダーシステムの設定です。
293     //!
294     //! @return       生成したスクリーンバッファを返します。
295     //---------------------------------------------------------------------------
296 
297     static nw::gfx::IRenderTarget* CreateUpperScreenBuffer(
298         os::IAllocator* allocator,
299         nw::demo::RenderSystem::Description& renderDescription
300     );
301 
302     //---------------------------------------------------------------------------
303     //! @brief        下画面用のスクリーンバッファを生成します。
304     //!
305     //!               レンダーシステムの設定をもとにバッファサイズなどが決定されます。
306     //!
307     //! @param[in]    allocator 生成に使用するアロケーターです。
308     //! @param[in]    renderDescription レンダーシステムの設定です。
309     //!
310     //! @return       生成したスクリーンバッファを返します。
311     //---------------------------------------------------------------------------
312 
313     static nw::gfx::IRenderTarget* CreateLowerScreenBuffer(
314         os::IAllocator* allocator,
315         nw::demo::RenderSystem::Description& renderDescription
316     );
317 
318     //@}
319 
320     //=====================
321     //! @name シーンノード関連
322     //@{
323 
324     //---------------------------------------------------------------------------
325     //! @brief        シーンオブジェクトのリソースからシーンノードのインスタンスを生成します。
326     //!
327     //! @param[in]    deviceAllocator 生成に使用するデバイスメモリのアロケーターです。
328     //! @param[in]    resource シーンオブジェクトのリソースです。
329     //! @param[in]    isAnimationEnabled アニメーションが有効かどうかを指定します。
330     //! @param[in]    bufferOption バッファの種類です。
331     //! @param[in]    maxAnimObjects AnimBindingが持てるAnimGroupごとのAnimObjectの最大数です。
332     //!
333     //! @return       生成したインスタンスを返します。
334     //---------------------------------------------------------------------------
335     static nw::gfx::SceneNode* CreateSceneNode(
336         os::IAllocator* deviceAllocator,
337         nw::gfx::ResSceneObject resource,
338         bool isAnimationEnabled = true,
339         nw::gfx::Model::BufferOption bufferOption = nw::gfx::Model::FLAG_BUFFER_NOT_USE,
340         s32 maxAnimObjects = 1
341     );
342 
343     //---------------------------------------------------------------------------
344     //! @brief          指定した名前のシーンオブジェクトを検索します。
345     //!
346     //!                 コレクションから指定した名前のシーンオブジェクトを探します。
347     //!                 線形探索を行っていますので、要素数の大きなコレクションを対象にする場合は注意が必要です。
348     //!
349     //!                 見つからなければ NULL を返します。
350     //!                 また、同じ名前のオブジェクトが複数存在する場合、最初に見つかったオブジェクトを返します。
351     //!
352     //! @param[in]      objects シーンオブジェクトのコレクションです。
353     //! @param[in]      objectName シーンオブジェクトの名前です。
354     //!
355     //! @return         見つかったシーンオブジェクトを返します。
356     //---------------------------------------------------------------------------
357     template <class TObjectArray>
FindObjectByName(TObjectArray & objects,const char * objectName)358     static nw::gfx::SceneObject* FindObjectByName(
359         TObjectArray& objects,
360         const char* objectName
361     )
362     {
363         // 指定した名前を持つシーンオブジェクトを探します。
364         nw::gfx::SceneObject* targetObject = NULL;
365 
366         typename TObjectArray::iterator objEnd = objects.end();
367         for (typename TObjectArray::iterator obj = objects.begin(); obj != objEnd; ++obj)
368         {
369             if (std::strcmp(objectName, (*obj)->GetName()) == 0)
370             {
371                 targetObject = *obj;
372                 break;
373             }
374         }
375 
376         return targetObject;
377     }
378 
379     //@}
380 
381     //=====================
382     //! @name アニメーション
383     //@{
384 
385     //---------------------------------------------------------------------------
386     //! @brief          指定した名前のアニメーションリソースを検索します。
387     //!
388     //!                 コレクションから指定した名前と種類のアニメーションリソースを探します。
389     //!                 コレクションの線形探索を行っていますので、要素数の大きなコレクションを対象にする場合は注意が必要です。
390     //!
391     //!                 見つからなければ無効なリソースを返しますので、IsValid() 関数で戻り値をチェックしてください。
392     //!                 また、同じ名前のリソースが複数存在する場合、最初に見つかったリソースを返します。
393     //!
394     //! @param[in]      resources アニメーションリソースのコレクションです。
395     //! @param[in]      animationName アニメーションリソースの名前です。
396     //! @param[in]      animationType アニメーションの種類です。
397     //!
398     //! @return         見つかったアニメーションリソースを返します。
399     //---------------------------------------------------------------------------
400     template <class TResArray>
FindResAnimByName(TResArray & resources,const char * animationName,AnimationType animationType)401     static nw::anim::ResAnim FindResAnimByName(
402         TResArray& resources,
403         const char* animationName,
404         AnimationType animationType
405     )
406     {
407         nw::anim::ResAnim resAnim;
408 
409         typename TResArray::iterator resEnd = resources.end();
410         for (typename TResArray::iterator res = resources.begin(); res != resEnd; ++res)
411         {
412             switch (animationType)
413             {
414             case SKELETAL_ANIMATION:
415                 resAnim = res->GetSkeletalAnims(animationName);
416                 break;
417             case MATERIAL_ANIMATION:
418                 resAnim = res->GetMaterialAnims(animationName);
419                 break;
420             case VISIBILITY_ANIMATION:
421                 resAnim = res->GetVisibilityAnims(animationName);
422                 break;
423             case CAMERA_ANIMATION:
424                 resAnim = res->GetCameraAnims(animationName);
425                 break;
426             case LIGHT_ANIMATION:
427                 resAnim = res->GetLightAnims(animationName);
428                 break;
429             default:
430                 NW_FATAL_ERROR("Invalid animation type");
431             }
432 
433             if (resAnim.IsValid())
434             {
435                 break;
436             }
437         }
438 
439         return resAnim;
440     }
441 
442 
443     //---------------------------------------------------------------------------
444     //! @brief          アニメーションをバインドします。
445     //!
446     //!                 アニメーションオブジェクトを生成し、指定したシーンオブジェクトとバインドします。
447     //!
448     //!                 シーンオブジェクトに指定した種類のアニメーショングループが存在しない場合や、
449     //!                 バインドに失敗した場合にこの関数は失敗し、NULL を返します。
450     //!
451     //!                 生成されるアニメーションオブジェクトは、
452     //!                 スケルタルアニメーションの場合は nw::gfx::TransformAnimEvaluator 、
453     //!                 その他の場合は nw::gfx::AnimEvaluator です。
454     //!
455     //! @param[in]      allocator アニメーションオブジェクトの生成に使用するアロケータです。
456     //! @param[in]      object シーンオブジェクトです。
457     //! @param[in]      resAnim アニメーションデータを持つアニメーションリソースです。
458     //! @param[in]      animationType アニメーションの種類です。
459     //! @param[in]      allocCache キャッシュバッファを確保してキャッシュを有効にするかどうかを設定します。
460     //!
461     //! @return         生成したアニメーションオブジェクトを返します。
462     //!
463     //! @sa             BindAnimationByName
464     //! @sa             nw::gfx::AnimObject::Bind
465     //! @sa             nw::gfx::SkeletalModel::SetSkeletalAnimObject
466     //! @sa             nw::gfx::Model::SetMaterialAnimObject
467     //! @sa             nw::gfx::Model::SetVisibilityAnimObject
468     //! @sa             nw::gfx::Camera::SetAnimObject
469     //! @sa             nw::gfx::Light::SetAnimObject
470     //---------------------------------------------------------------------------
BindAnimation(os::IAllocator * allocator,nw::gfx::SceneObject * object,nw::anim::ResAnim resAnim,AnimationType animationType,bool allocCache)471     static nw::gfx::BaseAnimEvaluator* BindAnimation(
472         os::IAllocator* allocator,
473         nw::gfx::SceneObject* object,
474         nw::anim::ResAnim resAnim,
475         AnimationType animationType,
476         bool allocCache
477     )
478     {
479         // アニメーショングループを取得します。
480         nw::gfx::AnimGroup* animGroup = GetAnimGroup(object, animationType);
481         if (!animGroup)
482         {
483             NW_LOG("BindAnimation() : Specified type animation group not found\n");
484             return NULL;
485         }
486 
487         // アニメーションオブジェクトを生成します。
488         nw::gfx::BaseAnimEvaluator* animObject;
489         if (animationType == SKELETAL_ANIMATION)
490         {
491             animObject = nw::gfx::TransformAnimEvaluator::Builder()
492                 .AnimData(resAnim)
493                 .MaxMembers(animGroup->GetMemberCount())
494                 .MaxAnimMembers(resAnim.GetMemberAnimSetCount())
495                 .AllocCache(allocCache)
496                 .Create(allocator);
497         }
498         else
499         {
500             animObject = nw::gfx::AnimEvaluator::Builder()
501                 .AnimData(resAnim)
502                 .MaxMembers(animGroup->GetMemberCount())
503                 .MaxAnimMembers(resAnim.GetMemberAnimSetCount())
504                 .AllocCache(allocCache)
505                 .Create(allocator);
506         }
507         NW_NULL_ASSERT(animObject);
508 
509         // スケルタルアニメーションであればであれば
510         // 移動アニメーションの無効化フラグを設定します。
511         if (animationType == SKELETAL_ANIMATION)
512         {
513             nw::gfx::SkeletalModel* skeletalModel =
514                 nw::ut::DynamicCast<nw::gfx::SkeletalModel*>(object);
515             nw::gfx::ResSkeleton resSkeleton = skeletalModel->GetSkeleton()->GetResSkeleton();
516             const bool translateAnimEnabled = nw::ut::CheckFlag(
517                 resSkeleton.GetFlags(),
518                 nw::gfx::ResSkeletonData::FLAG_TRANSLATE_ANIMATION_ENABLED
519             );
520             reinterpret_cast<nw::gfx::TransformAnimEvaluator*>(animObject)
521                 ->SetIsTranslateDisabled(!translateAnimEnabled);
522         }
523 
524         // アニメーションオブジェクトとシーンオブジェクトをバインドします。
525         if (!BindAnimationObject(object, animObject, animationType))
526         {
527 
528             NW_LOG("BindAnimation() : Failed to bind animation object\n");
529             nw::ut::SafeDestroy(animObject);
530             return NULL;
531         }
532 
533         return animObject;
534     }
535 
536 
537     //---------------------------------------------------------------------------
538     //! @brief          アニメーションブレンダーをバインドします。
539     //!
540     //!                 アニメーションブレンダーオブジェクトを生成し、指定したシーンオブジェクトとバインドします。
541     //!
542     //!                 シーンオブジェクトに指定した種類のアニメーショングループが存在しない場合や、
543     //!                 バインドに失敗した場合にこの関数は失敗し、NULL を返します。
544     //!
545     //! @tparam         TAnimObject  生成するアニメーションオブジェクトクラスです。
546     //! @param[in]      allocator アニメーションオブジェクトの生成に使用するアロケータです。
547     //! @param[in]      object シーンオブジェクトです。
548     //! @param[in]      maxAnimObjects 生成するブレンダーの最大アニメーションオブジェクト数です。
549     //! @param[in]      animationType アニメーションの種類です。
550     //!
551     //! @return         生成したアニメーションブレンダーオブジェクトを返します。
552     //!
553     //! @sa             BindAnimation
554     //! @sa             BindAnimationByName
555     //---------------------------------------------------------------------------
556     template <typename TAnimObject>
BindAnimationBlender(os::IAllocator * allocator,nw::gfx::SceneObject * object,int maxAnimObjects,AnimationType animationType)557     static TAnimObject* BindAnimationBlender(
558         os::IAllocator* allocator,
559         nw::gfx::SceneObject* object,
560         int maxAnimObjects,
561         AnimationType animationType
562     )
563     {
564         // アニメーショングループを取得します。
565         nw::gfx::AnimGroup* animGroup = GetAnimGroup(object, animationType);
566         if (!animGroup)
567         {
568             NW_LOG("BindAnimationBlender() : Specified type animation group not found\n");
569             return NULL;
570         }
571 
572         // アニメーションオブジェクトを生成します。
573         TAnimObject* animObject = TAnimObject::Builder()
574             .MaxAnimObjects(maxAnimObjects)
575             .Create(allocator);
576         NW_NULL_ASSERT(animObject);
577 
578 
579         // アニメーションオブジェクトとシーンオブジェクトをバインドします。
580         if (!BindAnimationObject(object, animObject, animationType))
581         {
582             NW_LOG("BindAnimationBlender() : Failed to bind animation object\n");
583             nw::ut::SafeDestroy(animObject);
584             return NULL;
585         }
586 
587         return animObject;
588     }
589 
590     //---------------------------------------------------------------------------
591     //! @brief          名前を指定してアニメーションをバインドします。
592     //!
593     //!                 指定した名前のオブジェクトとアニメーションデータを探してバインドします。
594     //!                 指定した名前のオブジェクトやアニメーションデータが見つからない場合や、
595     //!                 オブジェクトに指定した種類のアニメーショングループが存在しない場合、
596     //!                 バインドに失敗した場合にこの関数は失敗し、 NULL を返します。
597     //!
598     //!                 同じ名前のオブジェクトやアニメーションデータが存在する場合、
599     //!                 一番最初に見つかったものが使用されます。
600     //!
601     //!                 生成されるアニメーションオブジェクトは、
602     //!                 スケルタルアニメーションの場合は nw::gfx::TransformAnimEvaluator 、
603     //!                 その他の場合は nw::gfx::AnimEvaluator です。
604     //!
605     //! @tparam         TObjectArray  シーンオブジェクトのコレクション型です。
606     //! @tparam         TResArray  リソースのコレクション型です。
607     //! @param[in]      allocator アニメーションオブジェクトの生成に使用するアロケータです。
608     //! @param[in]      objects シーンオブジェクトのコレクションです。
609     //! @param[in]      resources リソースのコレクションです。
610     //! @param[in]      objectName オブジェクトの名前です。
611     //! @param[in]      animationName アニメーションデータの名前です。
612     //! @param[in]      animationType アニメーションの種類です。
613     //! @param[in]      allocCache キャッシュバッファを確保してキャッシュを有効にするかどうかを設定します。
614     //!
615     //! @return         生成したアニメーションオブジェクトを返します。
616     //!
617     //! @sa             BindAnimation
618     //! @sa             FindObjectByName
619     //! @sa             FindResAnimByName
620     //---------------------------------------------------------------------------
621     template <class TObjectArray, class TResArray>
BindAnimationByName(os::IAllocator * allocator,TObjectArray & objects,TResArray & resources,const char * objectName,const char * animationName,AnimationType animationType,bool allocCache)622     static nw::gfx::BaseAnimEvaluator* BindAnimationByName(
623         os::IAllocator* allocator,
624         TObjectArray& objects,
625         TResArray& resources,
626         const char* objectName,
627         const char* animationName,
628         AnimationType animationType,
629         bool allocCache
630     )
631     {
632         nw::gfx::SceneObject* targetObject = FindObjectByName(objects, objectName);
633 
634         if (!targetObject)
635         {
636             // 指定した名前のオブジェクトが見つからなかった場合 NULL を返します。
637             NW_LOG("BindAnimationByName() : Specified object not found [%s]\n", objectName);
638             return NULL;
639         }
640 
641 
642         // 指定した名前を持つアニメーションデータを探します。
643         nw::anim::ResAnim resAnim = FindResAnimByName(resources, animationName, animationType);
644 
645         if (!resAnim.IsValid())
646         {
647             // 指定した種類と名前のアニメーションデータが見つからなかった場合 NULL を返します。
648             NW_LOG("BindAnimationByName() : Specified animation resource not found [%s]\n", animationName);
649             return NULL;
650         }
651 
652         // アニメーションをバインドします。
653         nw::gfx::BaseAnimEvaluator* animObject = BindAnimation(
654             allocator,
655             targetObject,
656             resAnim,
657             animationType,
658             allocCache);
659 
660         return animObject;
661     }
662 
663     //---------------------------------------------------------------------------
664     //! @brief          アニメーショングループを取得します。
665     //!
666     //!                 シーンオブジェクトから指定した種類のアニメーショングループを取得します。
667     //!                 取得できない場合は NULL を返します。
668     //!
669     //! @param[in]      object シーンオブジェクトです。
670     //! @param[in]      animationType アニメーションの種類です。
671     //!
672     //! @return         取得したアニメーショングループを返します。
673     //---------------------------------------------------------------------------
674     static nw::gfx::AnimGroup* GetAnimGroup(
675         nw::gfx::SceneObject* object,
676         AnimationType animationType
677     );
678 
679 
680     //@}
681 
682     //=====================
683     //! @name 状態の取得
684     //@{
685 
686     //---------------------------------------------------------------------------
687     //! @brief        デモが終了状態かどうかを取得します。
688     //!
689     //!               NW_DEBUG_CHECK_MEMORY_LEAK マクロが有効な場合は、
690     //!               パッドのスタートボタンでも終了処理をおこなう為に true を返します。
691     //!               この関数はパッドの更新などを行わないので、あらかじめ PadFactory を初期化し、
692     //!               Pad::Update() 関数でパッドの状態を更新しておく必要があります。
693     //!
694     //! @return       終了状態の場合は true、そうでない場合は false を返します。
695     //---------------------------------------------------------------------------
696     static bool
IsTerminating()697     IsTerminating()
698     {
699         #if defined(NW_DEBUG_CHECK_MEMORY_LEAK)
700             nw::demo::Pad* pad = nw::demo::PadFactory::GetPad();
701             if (pad->IsButtonDown(nw::demo::Pad::BUTTON_START))
702             {
703                 return true;
704             }
705         #endif //defined(NW_DEBUG_CHECK_MEMORY_LEAK)
706 
707         return internal::IsTerminatingImpl();
708     }
709 
710     //@}
711 
712 private:
713 
714     //---------------------------------------------------------------------------
715     //! @brief          アニメーションオブジェクトとシーンオブジェクトをバインドします。
716     //!
717     //!                 アニメーションオブジェクトにシーンオブジェクトのアニメーショングループをバインドし、
718     //!                 シーンオブジェクトにアニメーションオブジェクトを設定します。
719     //!
720     //! @param[in]      object シーンオブジェクトです。
721     //! @param[in]      animObject アニメーションオブジェクトです。
722     //! @param[in]      animationType アニメーションの種類です。
723     //!
724     //! @return         成功したら trueを返します。
725     //---------------------------------------------------------------------------
726     static bool BindAnimationObject(
727         nw::gfx::SceneObject* object,
728         nw::gfx::AnimObject* animObject,
729         AnimationType animationType
730     );
731 };
732 
733 //@}
734 
735 //============================================================================
736 //! @name パーティクルユーティリティ
737 //@{
738 
739 /*!--------------------------------------------------------------------------*
740   @brief        キャッシュをフラッシュするテストコードです。
741  *---------------------------------------------------------------------------*/
742 class FlushCache
743 {
744 public:
745     //! @brief FulshCache クラスのインスタンスを生成します。
746     //!
747     //! @param[in] allocator 生成に使用するアロケーターです。
Create(nw::demo::DemoAllocator * allocator)748     static FlushCache* Create(nw::demo::DemoAllocator* allocator)
749     {
750         void* memory = allocator->Alloc(sizeof(FlushCache));
751         NW_NULL_ASSERT(memory);
752         return new (memory) FlushCache(allocator);
753     }
754 
755     //! @brief インスタンスを破棄します。
Destroy()756     void Destroy()
757     {
758         nw::os::IAllocator* allocator = m_Allocator;
759         this->~FlushCache();
760         allocator->Free(this);
761     }
762 
763     //! @brief キャッシュをフラッシュします。
764     void
Execute()765     Execute()
766     {
767         if (m_Buffer != NULL)
768         {
769             ::std::memcpy(m_Buffer + BufferSize / 2, m_Buffer, BufferSize / 2);
770         }
771     }
772 
773 private:
774     //! @brief コンストラクタです。
FlushCache(nw::demo::DemoAllocator * allocator)775     FlushCache(nw::demo::DemoAllocator* allocator)
776     {
777         m_Allocator = allocator;
778         m_Buffer = NULL;
779 
780         if (m_Allocator != NULL)
781         {
782             m_Buffer = (u8*)m_Allocator->Alloc(BufferSize);
783             NW_ASSERT(nw::os::IsDeviceMemory(m_Buffer));
784         }
785     }
786 
787     //! @brief デストラクタです。
~FlushCache()788     ~FlushCache()
789     {
790         if (m_Buffer != NULL)
791         {
792             m_Allocator->Free(m_Buffer);
793         }
794     }
795 
796     static const int BufferSize = 16 * 1024 * 2;
797     u8* m_Buffer;
798     nw::demo::DemoAllocator* m_Allocator;
799 };
800 
801 //@}
802 
803 } // namespace demo
804 } // namespace nw
805 
806 #endif // NW_DEMO_UTILITY_H_
807