1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     gfx_Skeleton.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: 25777 $
14  *---------------------------------------------------------------------------*/
15 
16 #ifndef NW_GFX_SKELETON_H_
17 #define NW_GFX_SKELETON_H_
18 
19 #include <nw/gfx/gfx_SceneObject.h>
20 #include <nw/gfx/res/gfx_ResSkeleton.h>
21 #include <nw/ut/ut_Signal.h>
22 
23 namespace nw
24 {
25 namespace math
26 {
27 struct MTX34;
28 struct Transform3;
29 }
30 
31 namespace gfx
32 {
33 
34 class SkeletalModel;
35 class CalculatedTransform;
36 
37 //---------------------------------------------------------------------------
38 //! @brief        SkeletalModel 内の階層構造を表すインターフェースです。
39 //!
40 //! ISkeleton は廃止され Skeleton に変更されました。
41 //---------------------------------------------------------------------------
42 class Skeleton  : public SceneObject
43 {
44 private:
45     NW_DISALLOW_COPY_AND_ASSIGN(Skeleton);
46 
47 public:
48     NW_UT_RUNTIME_TYPEINFO;
49 
50     //! @brief マトリクス計算時に呼ばれるコールバック用シグナルの定義です。
51     //!
52     //! @sa PreCalculateMatrixSignal
53     //! @sa PostCalculateMatrixSignal
54     typedef ut::Signal2<void, Skeleton*, int> CalculateMatrixSignal;
55 
56     //! @brief マトリクス計算時に呼ばれるコールバック用スロットの定義です。
57     typedef CalculateMatrixSignal::SlotType CalculateMatrixSlot;
58 
59     //! 動きを付けられるポーズを表すクラスです。
60     class TransformPose
61     {
62     private:
63         NW_DISALLOW_COPY_AND_ASSIGN(TransformPose);
64 
65     public:
66         //! 計算済みトランスフォームを表す定義です。
67         typedef CalculatedTransform Transform;
68         //! トランスフォームの配列を表す定義です。
69         typedef ut::MoveArray<Transform> TransformArray;
70         //! トランスフォームの配列の範囲を表す定義です。
71         typedef std::pair<TransformArray::iterator, TransformArray::iterator> TransformRange;
72         //! トランスフォームの配列の範囲を表す定義です。
73         typedef std::pair<TransformArray::const_iterator, TransformArray::const_iterator> ConstTransformRange;
74 
75         //! コンストラクタです。
TransformPose()76         TransformPose() {}
77 
78         //! コンストラクタです。
TransformPose(TransformArray & transforms)79         explicit TransformPose(TransformArray& transforms) : m_Transforms(transforms) {}
80 
81         //! ボーンの数を取得します。
GetBonesCount()82         int GetBonesCount() const { return m_Transforms.Size(); }
83 
84         //! トランスフォームを取得します。
GetTransform(int index,Transform ** transform)85         bool GetTransform(int index, Transform** transform)
86         {
87             if (index < 0 || this->GetBonesCount() <= index) { return false; }
88             *transform = &this->m_Transforms[index];
89             return true;
90         }
91 
92         //! トランスフォームを取得します。
GetTransform(int index,const Transform ** transform)93         bool GetTransform(int index, const Transform** transform) const
94         {
95             if (index < 0 || this->GetBonesCount() <= index) { return false; }
96             *transform = &this->m_Transforms[index];
97             return true;
98         }
99 
100         //! トランスフォームを取得します。
GetTransform(int index)101         Transform* GetTransform(int index)
102         {
103             return &this->m_Transforms[index];
104         }
105 
106         //! トランスフォームを取得します。
GetTransform(int index)107         const Transform* GetTransform(int index) const
108         {
109             return &this->m_Transforms[index];
110         }
111 
112         //! トランスフォームの先頭を指すイテレータを取得します。
GetBeginTransform()113         TransformArray::iterator GetBeginTransform() { return m_Transforms.Begin(); }
114 
115         //! トランスフォームの終端を指すイテレータを取得します。
GetEndTransform()116         TransformArray::iterator GetEndTransform() { return m_Transforms.End(); }
117 
118         //! トランスフォームの先頭と終端を指すイテレータを取得します。
GetAllTransforms()119         TransformRange GetAllTransforms()
120         {
121             return TransformRange(m_Transforms.Begin(), m_Transforms.End());
122         }
123 
124         //! トランスフォームの先頭と終端を指すイテレータを取得します。
GetAllTransforms()125         ConstTransformRange GetAllTransforms() const
126         {
127             return ConstTransformRange(m_Transforms.Begin(), m_Transforms.End());
128         }
129 
130     private:
131         TransformArray m_Transforms;
132     };
133 
134     //! スケルトンのマトリクスを表すクラスです。
135     class MatrixPose
136     {
137     private:
138         NW_DISALLOW_COPY_AND_ASSIGN(MatrixPose);
139 
140     public:
141         //! マトリクスの配列を表す定義です。
142         typedef ut::MoveArray<math::MTX34> MatrixArray;
143         //! マトリクスの配列の範囲を表す定義です。
144         typedef std::pair<MatrixArray::iterator, MatrixArray::iterator> MatrixRange;
145         //! マトリクスの配列の範囲を表す定義です。
146         typedef std::pair<MatrixArray::const_iterator, MatrixArray::const_iterator> ConstMatrixRange;
147 
148         //! コンストラクタです。
MatrixPose()149         MatrixPose() {}
150 
151         //! コンストラクタです。
MatrixPose(MatrixArray & matrices)152         explicit MatrixPose(MatrixArray& matrices) : m_Matrices(matrices) {}
153 
154         //! ボーンの数を取得します。
GetBonesCount()155         int GetBonesCount() const { return m_Matrices.Size(); }
156 
157         //! マトリクスを取得します。
GetMatrix(int index,math::MTX34 ** matrix)158         bool GetMatrix(int index, math::MTX34** matrix)
159         {
160             if (index < 0 || this->GetBonesCount() <= index) { return false; }
161             *matrix = &this->m_Matrices[index];
162             return true;
163         }
164 
165         //! マトリクスを取得します。
GetMatrix(int index,const math::MTX34 ** matrix)166         bool GetMatrix(int index, const math::MTX34** matrix) const
167         {
168             if (index < 0 || this->GetBonesCount() <= index) { return false; }
169             *matrix = &this->m_Matrices[index];
170             return true;
171         }
172 
173         //! マトリクスを取得します。
GetMatrix(int index)174         math::MTX34* GetMatrix(int index)
175         {
176             return &this->m_Matrices[index];
177         }
178 
179         //! マトリクスを取得します。
GetMatrix(int index)180         const math::MTX34* GetMatrix(int index) const
181         {
182             return &this->m_Matrices[index];
183         }
184 
185         //! マトリクスの先頭を指すイテレータを取得します。
GetBeginMatrix()186         MatrixArray::iterator GetBeginMatrix() { return m_Matrices.Begin(); }
187 
188         //! マトリクスの終端を指すイテレータを取得します。
GetEndMatrix()189         MatrixArray::iterator GetEndMatrix() { return m_Matrices.End(); }
190 
191         //! マトリクスの先頭と終端を指すイテレータを取得します。
GetAllMatrices()192         MatrixRange GetAllMatrices()
193         {
194             return MatrixRange(m_Matrices.Begin(), m_Matrices.End());
195         }
196 
197         //! マトリクスの先頭と終端を指すイテレータを取得します。
GetAllMatrices()198         ConstMatrixRange GetAllMatrices() const
199         {
200             return ConstMatrixRange(m_Matrices.Begin(), m_Matrices.End());
201         }
202 
203     private:
204         MatrixArray m_Matrices;
205     };
206 
207     //! スケルトンの最初のポーズを表すクラスです。
208     class OriginalPose
209     {
210     private:
211         NW_DISALLOW_COPY_AND_ASSIGN(OriginalPose);
212 
213     public:
214         //! nw::math::Transform3 を表す定義です。
215         typedef math::Transform3 Transform;
216 
217         //! コンストラクタです。
OriginalPose(ResSkeleton resource)218         explicit OriginalPose(ResSkeleton resource) : m_Resource(resource) {}
219 
220         //! ボーンの数を取得します。
GetBonesCount()221         int GetBonesCount() const { return m_Resource.GetBonesCount(); }
222 
223         //! トランスフォームを取得します。
GetTransform(int index,Transform ** transform)224         bool GetTransform(int index, Transform** transform)
225         {
226             if (index < 0 || this->GetBonesCount() <= index) { return false; }
227             ResBone bone = m_Resource.GetBones(index);
228             if (!bone.IsValid()) { return false; }
229             *transform = &bone.GetTransform();
230             return true;
231         }
232 
233         //! トランスフォームを取得します。
GetTransform(int index,const Transform ** transform)234         bool GetTransform(int index, const Transform** transform) const
235         {
236             if (index < 0 || this->GetBonesCount() <= index) { return false; }
237             ResBone bone = m_Resource.GetBones(index);
238             if (!bone.IsValid()) { return false; }
239             *transform = &bone.GetTransform();
240             return true;
241         }
242 
243         //! トランスフォームを取得します。
GetTransform(int index)244         Transform* GetTransform(int index)
245         {
246             return &m_Resource.GetBones(index).GetTransform();
247         }
248 
249         //! トランスフォームを取得します。
GetTransform(int index)250         const Transform* GetTransform(int index) const
251         {
252             return &m_Resource.GetBones(index).GetTransform();
253         }
254 
255     private:
256         ResSkeleton m_Resource;
257     };
258 
259     //----------------------------------------
260     //! @name リソース
261     //@{
262 
263     //! スケルトンのリソースを取得します。
GetResSkeleton()264     ResSkeleton GetResSkeleton()
265     {
266         return ResStaticCast<ResSkeleton>(this->GetResSceneObject());
267     }
268 
269     //! スケルトンのリソースを取得します。
GetResSkeleton()270     const ResSkeleton GetResSkeleton() const
271     {
272         return ResStaticCast<ResSkeleton>(this->GetResSceneObject());
273     }
274 
275     //@}
276 
277     //----------------------------------------
278     //! @name 更新
279     //@{
280 
281     //! @brief スケルトンが更新済みかどうかを取得します。
IsUpdated()282     bool IsUpdated()
283     {
284         return this->m_IsUpdated;
285     }
286 
287     //! @brief スケルトンが更新済みかどうかを設定します。
SetUpdated(bool isUpdated)288     void SetUpdated(bool isUpdated)
289     {
290         this->m_IsUpdated = isUpdated;
291     }
292 
293     //@}
294 
295     //----------------------------------------
296     //! @name 所有者
297     //@{
298 
299     //! 所有者となるスケルタルモデルを取得します。
GetOwnerSkeletalModel()300     const SkeletalModel* GetOwnerSkeletalModel() const { return m_OwnerSkeletalModel; }
301 
302     //! 所有者となるスケルタルモデルを取得します。
GetOwnerSkeletalModel()303     SkeletalModel* GetOwnerSkeletalModel() { return m_OwnerSkeletalModel; }
304 
305     //! 所有者となるスケルタルモデルを設定します。
SetOwnerSkeletalModel(SkeletalModel * ownerSkeletalModel)306     void SetOwnerSkeletalModel(SkeletalModel* ownerSkeletalModel)
307     {
308         m_OwnerSkeletalModel = ownerSkeletalModel;
309     }
310 
311     //@}
312 
313     //----------------------------------------
314     //! @name ポーズ
315     //@{
316 
317     //! @brief        ローカルトランスフォームのポーズを取得します。
318     //!
319     //! @return       ローカルトランスフォームのポーズです。
320     //!
321     virtual TransformPose& LocalTransformPose() = 0;
322 
323     //! @brief        ローカルトランスフォームのポーズを取得します。
324     //!
325     //! @return       ローカルトランスフォームのポーズです。
326     //!
327     virtual const TransformPose& LocalTransformPose() const = 0;
328 
329     //! @brief        ワールドトランスフォームのポーズを取得します。
330     //!
331     //! @return       ワールドトランスフォームのポーズです。
332     //!
333     virtual TransformPose& WorldTransformPose() = 0;
334 
335     //! @brief        ワールドトランスフォームのポーズを取得します。
336     //!
337     //! @return       ワールドトランスフォームのポーズです。
338     //!
339     virtual const TransformPose& WorldTransformPose() const = 0;
340 
341     //! @brief        ワールドマトリクスのポーズを取得します。
342     //!
343     //! @return       ワールドマトリクスのポーズです。
344     //!
345     virtual MatrixPose& WorldMatrixPose() = 0;
346 
347     //! @brief        ワールドマトリクスのポーズを取得します。
348     //!
349     //! @return       ワールドマトリクスのポーズです。
350     //!
351     virtual const MatrixPose& WorldMatrixPose() const = 0;
352 
353     //! @brief        スキニングマトリクスのポーズを取得します。
354     //!
355     //! @return       スキニングマトリクスのポーズです。
356     //!
357     virtual MatrixPose& SkiningMatrixPose() = 0;
358 
359     //! @brief        スキニングマトリクスのポーズを取得します。
360     //!
361     //! @return       スキニングマトリクスのポーズです。
362     //!
363     virtual const MatrixPose& SkiningMatrixPose() const = 0;
364 
365     //! @brief        オリジナルポーズを取得します。
366     //!
367     //! @return       オリジナルポーズです。
368     //!
369     virtual OriginalPose& LocalOriginalPose() = 0;
370 
371     //! @brief        オリジナルポーズを取得します。
372     //!
373     //! @return       オリジナルポーズです。
374     //!
375     virtual const OriginalPose& LocalOriginalPose() const = 0;
376 
377     //@}
378 
379     //----------------------------------------
380     //! @name コールバック
381     //@{
382 
383     //! @brief ボーンのマトリクス計算前のシグナルを取得します。
384     //!
385     //! @sa CalculateMatrixSignal
PreCalculateMatrixSignal()386     CalculateMatrixSignal& PreCalculateMatrixSignal() { return *m_PreCalculateMatrixSignal; }
387 
388     //! @brief ボーンのマトリクス計算前のシグナルを取得します。
389     //!
390     //! @sa CalculateMatrixSignal
PreCalculateMatrixSignal()391     const CalculateMatrixSignal& PreCalculateMatrixSignal() const { return *m_PreCalculateMatrixSignal; }
392 
393     //! @brief ボーンのマトリクス計算後のシグナルを取得します。
394     //!
395     //! @sa CalculateMatrixSignal
PostCalculateMatrixSignal()396     CalculateMatrixSignal& PostCalculateMatrixSignal() { return *m_PostCalculateMatrixSignal; }
397 
398     //! @brief ボーンのマトリクス計算後のシグナルを取得します。
399     //!
400     //! @sa CalculateMatrixSignal
PostCalculateMatrixSignal()401     const CalculateMatrixSignal& PostCalculateMatrixSignal() const { return *m_PostCalculateMatrixSignal; }
402 
403     //@}
404 
405 protected:
406     //----------------------------------------
407     //! @name コンストラクタ/デストラクタ
408     //@{
409 
410     //! コンストラクタです。
Skeleton(os::IAllocator * allocator,ResSkeleton resource,int maxCallbacks,bool isFixedSizeMemory)411     Skeleton(
412         os::IAllocator* allocator,
413         ResSkeleton resource,
414         int maxCallbacks,
415         bool isFixedSizeMemory)
416     :
417     SceneObject(allocator, resource),
418     m_PreCalculateMatrixSignal(NULL),
419     m_PostCalculateMatrixSignal(NULL),
420     m_IsUpdated(false)
421     {
422         this->SetOwnerSkeletalModel(NULL);
423         CreateCallbacks(allocator, maxCallbacks, isFixedSizeMemory);
424     }
425 
426     //! デストラクタです。
~Skeleton()427     virtual ~Skeleton()
428     {
429         SafeDestroy(this->m_PreCalculateMatrixSignal);
430         SafeDestroy(this->m_PostCalculateMatrixSignal);
431     }
432 
433     //@}
434 
435     //! @brief   コンストラクタの実行に必要なメモリサイズを取得します。
436     //!
437     //! @details :private
GetMemorySizeForConstruct(os::MemorySizeCalculator * pSize,int maxCallbacks)438     static void GetMemorySizeForConstruct(
439         os::MemorySizeCalculator* pSize,
440         int maxCallbacks)
441     {
442         // Skeleton::CreateCallbacks
443         if (maxCallbacks == 0)
444         {
445             CalculateMatrixSignal::GetMemorySizeForInvalidateSignalInternal(pSize);
446             CalculateMatrixSignal::GetMemorySizeForInvalidateSignalInternal(pSize);
447         }
448         else
449         {
450             CalculateMatrixSignal::GetMemorySizeForFixedSizedSignalInternal(pSize, maxCallbacks);
451             CalculateMatrixSignal::GetMemorySizeForFixedSizedSignalInternal(pSize, maxCallbacks);
452         }
453     }
454 
455 private:
456     //! コールバック関数を生成します。
457     void CreateCallbacks(os::IAllocator* allocator, int maxCallbacks, bool isFixedSizeMemory);
458 
459     SkeletalModel* m_OwnerSkeletalModel;
460 
461     CalculateMatrixSignal* m_PreCalculateMatrixSignal;
462     CalculateMatrixSignal* m_PostCalculateMatrixSignal;
463     bool m_IsUpdated;
464 };
465 
466 } // namespace gfx
467 } // namespace nw
468 
469 #endif // NW_GFX_SKELETON_H_
470