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