1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     gfx_WorldMatrixUpdater.h
4 
5   Copyright (C)2009-2011 Nintendo/HAL Laboratory, Inc.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain proprietary
8   information of Nintendo and/or its licensed developers and are protected by
9   national and international copyright laws. They may not be disclosed to third
10   parties or copied or duplicated in any form, in whole or in part, without the
11   prior written consent of Nintendo.
12 
13   The content herein is highly confidential and should be handled accordingly.
14 
15   $Revision: 31311 $
16  *---------------------------------------------------------------------------*/
17 
18 #ifndef NW_GFX_WORLD_MATRIX_UPDATER_H_
19 #define NW_GFX_WORLD_MATRIX_UPDATER_H_
20 
21 #include <nw/gfx/gfx_GfxObject.h>
22 
23 #include <nw/ut/ut_MoveArray.h>
24 #include <nw/math.h>
25 
26 namespace nw
27 {
28 namespace os
29 {
30 class IAllocator;
31 } // os
32 namespace gfx
33 {
34 
35 class CalculatedTransform;
36 
37 //---------------------------------------------------------------------------
38 //! @brief        ワールドマトリクスを更新するためのクラスです。
39 //---------------------------------------------------------------------------
40 class WorldMatrixUpdater : public GfxObject
41 {
42 private:
43     NW_DISALLOW_COPY_AND_ASSIGN(WorldMatrixUpdater);
44 
45 public:
46     //---------------------------------------------------------------------------
47     //! @brief        ボーンのスケーリング方式の定義です。
48     //---------------------------------------------------------------------------
49     enum ScalingRule
50     {
51         SCALING_RULE_STANDARD, //!< 標準的なスケーリング方式です。
52         SCALING_RULE_MAYA,     //!< Mayaのスケーリング方式です。
53         SCALING_RULE_SOFTIMAGE //!< Softimageのスケーリング方式です。
54     };
55 
56 public:
57     //! ワールドマトリクスアップデータを構築するクラスです。
58     class Builder
59     {
60     public:
61         //! コンストラクタです。
Builder()62         Builder() {}
63 
64         //! @brief        ワールドマトリクスアップデータを生成します。
65         //!
66         //! @param[in]    allocator アロケータです。
67         //!
68         //! @return       生成されたワールドマトリクスアップデータです。
69         //!
70         WorldMatrixUpdater* Create(os::IAllocator* allocator);
71 
72     };
73 
74     //! @brief         Maya方式でワールドマトリクスを更新します。
75     //!
76     //! @param[out]    worldMatrix          更新するワールドマトリクスです。
77     //! @param[out]    worldTransform       更新する計算済みワールドトランスフォームです。
78     //! @param[in]     localTransform       計算済みローカルトランスフォームです。
79     //! @param[in]     parentWorldTransform 親の計算済みワールドトランスフォームです。
80     //! @param[in]     parentLocalTransform 親の計算済みローカルトランスフォームです。
81     //! @param[in]     isSSC                MAYAのSSCによる計算を行うかどうかのフラグです。
82     //!
83     NW_INLINE void UpdateMaya(
84         math::MTX34* worldMatrix,
85         CalculatedTransform* worldTransform,
86         const CalculatedTransform& localTransform,
87         const CalculatedTransform& parentWorldTransform,
88         const CalculatedTransform& parentLocalTransform,
89         bool isSSC) const;
90 
91     //! @brief         XSI方式でワールドマトリクスを更新します。
92     //!
93     //! @param[out]    worldMatrix          更新するワールドマトリクスです。
94     //! @param[out]    worldTransform       更新する計算済みワールドトランスフォームです。
95     //! @param[in]     localTransform       計算済みローカルトランスフォームです。
96     //! @param[in]     parentWorldTransform 親の計算済みワールドトランスフォームです。
97     //! @param[in]     parentLocalTransform 親の計算済みローカルトランスフォームです。
98     //!
99     NW_INLINE void UpdateXsi(
100         math::MTX34* worldMatrix,
101         CalculatedTransform* worldTransform,
102         const CalculatedTransform& localTransform,
103         const CalculatedTransform& parentWorldTransform,
104         const CalculatedTransform& parentLocalTransform) const;
105 
106     //! @brief         通常の方式でワールドマトリクスを更新します。
107     //!
108     //! @param[out]    worldMatrix          更新するワールドマトリクスです。
109     //! @param[out]    worldTransform       更新する計算済みワールドトランスフォームです。
110     //! @param[in]     localTransform       計算済みローカルトランスフォームです。
111     //! @param[in]     parentWorldTransform 親の計算済みワールドトランスフォームです。
112     //! @param[in]     parentLocalTransform 親の計算済みローカルトランスフォームです。
113     //!
114     NW_INLINE void UpdateBasic(
115         math::MTX34* worldMatrix,
116         CalculatedTransform* worldTransform,
117         const CalculatedTransform& localTransform,
118         const CalculatedTransform& parentWorldTransform,
119         const CalculatedTransform& parentLocalTransform) const;
120 
121 private:
122     //! コンストラクタです。
123     WorldMatrixUpdater(
124         os::IAllocator* allocator);
125 
126     //! デストラクタです。
127     virtual ~WorldMatrixUpdater();
128 
129     void CalculateWorldXsi(
130         math::MTX34* transformMatrix,
131         math::VEC3* scale,
132         const CalculatedTransform& localTransform,
133         const CalculatedTransform& parentWorldTransform,
134         const CalculatedTransform& parentLocalTransform) const;
135 
136     void CalculateWorldMayaSsc(
137         math::MTX34* transformMatrix,
138         math::VEC3* scale,
139         const CalculatedTransform& localTransform,
140         const CalculatedTransform& parentWorldTransform,
141         const CalculatedTransform& parentLocalTransform) const;
142 
143     void CalculateWorldBasic(
144         math::MTX34* transformMatrix,
145         math::VEC3* scale,
146         const CalculatedTransform& localTransform,
147         const CalculatedTransform& parentWorldTransform,
148         const CalculatedTransform& parentLocalTransform) const;
149 
150     template<typename TMatrix, typename UMatrix>
MultScale(TMatrix * dstMatrix,const UMatrix * srcMatrix,const math::VEC3 & scale)151     void MultScale(TMatrix* dstMatrix, const UMatrix* srcMatrix, const math::VEC3& scale) const
152     {
153         dstMatrix->f._00 = srcMatrix->f._00 * scale.x;
154         dstMatrix->f._10 = srcMatrix->f._10 * scale.x;
155         dstMatrix->f._20 = srcMatrix->f._20 * scale.x;
156 
157         dstMatrix->f._01 = srcMatrix->f._01 * scale.y;
158         dstMatrix->f._11 = srcMatrix->f._11 * scale.y;
159         dstMatrix->f._21 = srcMatrix->f._21 * scale.y;
160 
161         dstMatrix->f._02 = srcMatrix->f._02 * scale.z;
162         dstMatrix->f._12 = srcMatrix->f._12 * scale.z;
163         dstMatrix->f._22 = srcMatrix->f._22 * scale.z;
164     }
165 
166     template<typename TMatrix>
ScaleMatrix(TMatrix * dstMatrix,const math::VEC3 & scale)167     void ScaleMatrix(TMatrix* dstMatrix, const math::VEC3& scale) const
168     {
169         dstMatrix->f._00 *= scale.x;
170         dstMatrix->f._10 *= scale.x;
171         dstMatrix->f._20 *= scale.x;
172 
173         dstMatrix->f._01 *= scale.y;
174         dstMatrix->f._11 *= scale.y;
175         dstMatrix->f._21 *= scale.y;
176 
177         dstMatrix->f._02 *= scale.z;
178         dstMatrix->f._12 *= scale.z;
179         dstMatrix->f._22 *= scale.z;
180     }
181 
CopyTranslate(math::MTX34 * dstMatrix,const math::MTX34 & srcMatrix)182     void CopyTranslate(math::MTX34* dstMatrix, const math::MTX34& srcMatrix) const
183     {
184         dstMatrix->f._03 = srcMatrix.f._03;
185         dstMatrix->f._13 = srcMatrix.f._13;
186         dstMatrix->f._23 = srcMatrix.f._23;
187     }
188 
AddTranslate(math::MTX34 * dstMatrix,const math::VEC3 & translate)189     void AddTranslate(math::MTX34* dstMatrix, const math::VEC3& translate) const
190     {
191         dstMatrix->f._03 += translate.x;
192         dstMatrix->f._13 += translate.y;
193         dstMatrix->f._23 += translate.z;
194     }
195 
CompensateScale(math::VEC3 & scale)196     void CompensateScale(math::VEC3& scale) const
197     {
198         // Restrict scale to over 1 / 1000000
199         const float MinimumScale = 0.001f * 0.001f;
200         float mag = (scale.x * scale.x + scale.y * scale.y + scale.z * scale.z);
201 
202         if (mag < MinimumScale)
203         {
204             scale.x = (scale.x < 0.0f) ? -MinimumScale : MinimumScale;
205             scale.y = (scale.y < 0.0f) ? -MinimumScale : MinimumScale;
206             scale.z = (scale.z < 0.0f) ? -MinimumScale : MinimumScale;
207         }
208     }
209 };
210 
211 //----------------------------------------
212 NW_INLINE void
UpdateMaya(math::MTX34 * worldMatrix,CalculatedTransform * worldTransform,const CalculatedTransform & localTransform,const CalculatedTransform & parentWorldTransform,const CalculatedTransform & parentLocalTransform,bool isSSC)213 WorldMatrixUpdater::UpdateMaya(
214     math::MTX34* worldMatrix,
215     CalculatedTransform* worldTransform,
216     const CalculatedTransform& localTransform,
217     const CalculatedTransform& parentWorldTransform,
218     const CalculatedTransform& parentLocalTransform,
219     bool isSSC) const
220 {
221     NW_NULL_ASSERT(worldMatrix);
222     NW_NULL_ASSERT(worldTransform);
223 
224     math::VEC3 scale;
225     // Update WorldTransform
226     if (isSSC)
227     {
228         CalculateWorldMayaSsc(
229             &worldTransform->m_TransformMatrix,
230             &scale,
231             localTransform,
232             parentWorldTransform,
233             parentLocalTransform
234         );
235     }
236     else
237     {
238         CalculateWorldBasic(
239             &worldTransform->m_TransformMatrix,
240             &scale,
241             localTransform,
242             parentWorldTransform,
243             parentLocalTransform
244         );
245     }
246 
247     this->CompensateScale(scale);
248 
249     worldTransform->m_Scale = scale;
250 
251     // Update WorldMatrix
252     math::MTX34MultScale(worldMatrix, worldTransform->m_TransformMatrix, localTransform.m_Scale);
253 
254 #if defined(NW_GFX_WORLD_MATRIX_FLAG_UPDATE_ENABLED)
255     worldTransform->UpdateFlags();
256 #else
257     worldTransform->ResetTransformFlags();
258     worldTransform->UpdateScaleFlags();
259 #endif
260 }
261 
262 //----------------------------------------
263 NW_INLINE void
UpdateBasic(math::MTX34 * worldMatrix,CalculatedTransform * worldTransform,const CalculatedTransform & localTransform,const CalculatedTransform & parentWorldTransform,const CalculatedTransform & parentLocalTransform)264 WorldMatrixUpdater::UpdateBasic(
265     math::MTX34* worldMatrix,
266     CalculatedTransform* worldTransform,
267     const CalculatedTransform& localTransform,
268     const CalculatedTransform& parentWorldTransform,
269     const CalculatedTransform& parentLocalTransform) const
270 {
271     NW_NULL_ASSERT(worldMatrix);
272     NW_NULL_ASSERT(worldTransform);
273 
274     math::VEC3 scale;
275 
276     // Update WorldTransform
277     CalculateWorldBasic(
278         &worldTransform->m_TransformMatrix,
279         &scale,
280         localTransform,
281         parentWorldTransform,
282         parentLocalTransform
283     );
284 
285     this->CompensateScale(scale);
286 
287     worldTransform->m_Scale = scale;
288 
289     // Update WorldMatrix
290     math::MTX34MultScale(worldMatrix, worldTransform->m_TransformMatrix, localTransform.m_Scale);
291 
292 #if defined(NW_GFX_WORLD_MATRIX_FLAG_UPDATE_ENABLED)
293     worldTransform->UpdateFlags();
294 #else
295     worldTransform->ResetTransformFlags();
296     worldTransform->UpdateScaleFlags();
297 #endif
298 }
299 
300 //----------------------------------------
301 NW_INLINE void
UpdateXsi(math::MTX34 * worldMatrix,CalculatedTransform * worldTransform,const CalculatedTransform & localTransform,const CalculatedTransform & parentWorldTransform,const CalculatedTransform & parentLocalTransform)302 WorldMatrixUpdater::UpdateXsi(
303     math::MTX34* worldMatrix,
304     CalculatedTransform* worldTransform,
305     const CalculatedTransform& localTransform,
306     const CalculatedTransform& parentWorldTransform,
307     const CalculatedTransform& parentLocalTransform) const
308 {
309     NW_NULL_ASSERT(worldMatrix);
310     NW_NULL_ASSERT(worldTransform);
311 
312     math::VEC3 scale;
313 
314     // Update WorldTransform
315     CalculateWorldXsi(
316         &worldTransform->m_TransformMatrix,
317         &scale,
318         localTransform,
319         parentWorldTransform,
320         parentLocalTransform
321     );
322 
323     this->CompensateScale(scale);
324 
325     worldTransform->m_Scale = scale;
326 
327     // Update WorldMatrix
328     math::MTX34MultScale(worldMatrix, worldTransform->m_TransformMatrix, worldTransform->m_Scale);
329 
330 #if defined(NW_GFX_WORLD_MATRIX_FLAG_UPDATE_ENABLED)
331     worldTransform->UpdateFlags();
332 #else
333     worldTransform->ResetTransformFlags();
334     worldTransform->UpdateScaleFlags();
335 #endif
336 }
337 
338 } // gfx
339 } // nw
340 
341 #endif // NW_GFX_WORLD_MATRIX_UPDATER_H_
342