1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     gfx_TransformNode.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_TRANSFORMNODE_H_
17 #define NW_GFX_TRANSFORMNODE_H_
18 
19 #include <nw/gfx/gfx_SceneNode.h>
20 
21 #include <nw/gfx/gfx_CalculatedTransform.h>
22 
23 namespace nw
24 {
25 namespace gfx
26 {
27 
28 //---------------------------------------------------------------------------
29 //! @brief        変換情報を持つシーンノードを表すクラスです。
30 //---------------------------------------------------------------------------
31 class TransformNode : public SceneNode
32 {
33 private:
34     NW_DISALLOW_COPY_AND_ASSIGN(TransformNode);
35 
36 public:
37     NW_UT_RUNTIME_TYPEINFO;
38 
39     //! @brief マトリクス計算時に呼ばれるコールバック用シグナルの定義です。
40     //!
41     //! @sa PostCalculateWorldMatrixSignal
42     typedef ut::Signal2<void, TransformNode*, SceneContext*> CalculateMatrixSignal;
43 
44     //! @brief マトリクス計算時に呼ばれるコールバック用スロットの定義です。
45     typedef CalculateMatrixSignal::SlotType CalculateMatrixSlot;
46 
47     //! @brief 設定内容です。
48     struct Description : public SceneNode::Description
49     {
50         //! @brief コンストラクタです。
DescriptionDescription51         Description(){}
52     };
53 
54     //----------------------------------------
55     //! @name 作成/破棄
56     //@{
57 
58     //! @brief トランスフォームノードを動的に構築するためのクラスです。
59     //!
60     //! IsFixedSizeMemory の初期値は true です。false に変更すると、各種最大数の設定は無視されます。
61     class DynamicBuilder
62     {
63     public:
64         //! @brief コンストラクタです。
DynamicBuilder()65         DynamicBuilder() {}
66         //! @brief デストラクタです。
~DynamicBuilder()67         ~DynamicBuilder() {}
68 
69         //! @brief 生成時以外にもメモリを確保するかどうかのフラグを設定します。
70         //!
71         //!        true を指定すると、生成時のみ固定サイズのメモリ確保を行います。
72         //!
73         //!        false を指定すると、生成時以外にも必要に応じて動的にメモリ確保が行われます。
IsFixedSizeMemory(bool isFixedSizeMemory)74         DynamicBuilder& IsFixedSizeMemory(bool isFixedSizeMemory)
75         {
76             m_Description.isFixedSizeMemory = isFixedSizeMemory;
77             return *this;
78         }
79 
80         //! @brief 子の最大数を設定します。
MaxChildren(int maxChildren)81         DynamicBuilder& MaxChildren(int maxChildren)
82         {
83             m_Description.maxChildren = maxChildren;
84             return *this;
85         }
86 
87         //! @brief 管理できるコールバックの最大数を設定します。
MaxCallbacks(int maxCallbacks)88         DynamicBuilder& MaxCallbacks(int maxCallbacks)
89         {
90             m_Description.maxCallbacks = maxCallbacks;
91             return *this;
92         }
93 
94         //! @brief        トランスフォームノードを生成します。
95         //!
96         //! @param[in]    allocator アロケータです。
97         //!
98         //! @return       生成したトランスフォームノードを返します。
99         //!
100         TransformNode* Create(os::IAllocator* allocator);
101 
102     private:
103         TransformNode::Description m_Description;
104     };
105 
106     //! @brief        リソースからトランスフォームノードを生成します。
107     //!
108     //! @param[in]    parent 親のノードです。
109     //! @param[in]    resource リソースです。
110     //! @param[in]    description 設定内容です。
111     //! @param[in]    allocator アロケータです。
112     //!
113     //! @return       生成されたトランスフォームノードです。
114     //!
115     static TransformNode* Create(
116         SceneNode* parent,
117         ResSceneObject resource,
118         const TransformNode::Description& description,
119         os::IAllocator* allocator);
120 
121     //@}
122 
123     //----------------------------------------
124     //! @name リソース
125     //@{
126 
127     //! @brief トランスフォームノードのリソースを取得します。
GetResTransformNode()128     ResTransformNode GetResTransformNode()
129     {
130         return ResStaticCast<ResTransformNode>( this->GetResSceneObject() );
131     }
132 
133     //! @brief トランスフォームノードのリソースを取得します。
GetResTransformNode()134     const ResTransformNode GetResTransformNode() const
135     {
136         return ResStaticCast<ResTransformNode>( this->GetResSceneObject() );
137     }
138 
139     //@}
140 
141     //----------------------------------------
142     //! @name トランスフォーム
143     //@{
144 
145     //! @brief 変換情報を取得します。
Transform()146     CalculatedTransform& Transform() { return m_Transform; }
147 
148     //! @brief 変換情報を取得します。
Transform()149     const CalculatedTransform& Transform() const { return m_Transform; }
150 
151     //! @brief ワールドマトリクスを取得します。
WorldMatrix()152     math::MTX34& WorldMatrix() { return m_WorldMatrix; }
153 
154     //! @brief ワールドマトリクスを取得します。
WorldMatrix()155     const math::MTX34& WorldMatrix() const { return m_WorldMatrix; }
156 
157     //! @brief WorldMatrix 計算後の詳細な変換情報を取得します。
158     //!
WorldTransform()159     CalculatedTransform& WorldTransform() { return m_CalculatedTransform; }
160 
161     //! @brief WorldMatrix 計算後の詳細な変換情報を取得します。
162     //!        TransformMatrix にはこのノードの Rotate と Translate に親ノードまでの Scale が掛かっています。
163     //!        Scale は親ノードまでの累積のスケールとなります。
WorldTransform()164     const CalculatedTransform& WorldTransform() const { return m_CalculatedTransform; }
165 
166     //! @brief ワールド行列の逆行列を取得します。2回目以降は、キャッシュを利用します。
167     const math::MTX34& InverseWorldMatrix() const;
168 
169     //! @brief ワールド行列の逆行列のキャッシュを無効化します。(ワールド行列を更新する際に呼び出します。)
170     void InvalidateInverseWorldMatrix();
171 
172     //! @brief 方向情報を更新します。
UpdateDirection()173     virtual void UpdateDirection() {}
174 
175     //! @brief        変換情報に関する更新を行います。
176     //!
177     //! @param[in]    worldMatrixUpdater ワールドマトリクス更新クラスです。
178     //! @param[in]    sceneContext シーンコンテキストです。
179     //!
180     virtual void UpdateTransform(
181         WorldMatrixUpdater* worldMatrixUpdater,
182         SceneContext* sceneContext);
183 
184     //@}
185 
186     //----------------------------------------
187     //! @name シーンツリー
188     //@{
189 
190     //! @brief        ビジターを受け付けます。
191     //!
192     //! @param[in]    visitor ビジターです。
193     //!
194     virtual void Accept(ISceneVisitor* visitor);
195 
196     //! @brief 親ノードをたどりワールドマトリクスを取得します。
TrackbackWorldMatrix()197     virtual const math::MTX34& TrackbackWorldMatrix() const
198     {
199         return this->WorldMatrix();
200     }
201 
202     //! @brief 親ノードをたどりワールドトランスフォームを取得します。
TrackbackWorldTransform()203     virtual const CalculatedTransform& TrackbackWorldTransform() const
204     {
205         return this->WorldTransform();
206     }
207 
208     //! @brief 親ノードをたどりローカルトランスフォームを取得します。
TrackbackLocalTransform()209     virtual const CalculatedTransform& TrackbackLocalTransform() const
210     {
211         return this->Transform();
212     }
213 
214     //! @brief 親ノードからのトランスフォーム変換情報を継承します。
215     NW_DEPRECATED_FUNCTION(NW_INLINE void InheritTransformStates());
216 
217     //! @brief 親ノードから変換情報を継承します。
218     NW_INLINE virtual void InheritTraversalResults();
219 
220     //@}
221 
222     //----------------------------------------
223     //! @name コールバック
224     //@{
225 
226     //! @brief ワールドマトリクス計算後のシグナルを取得します。
227     //!
228     //! @sa CalculateMatrixSignal
PostCalculateWorldMatrixSignal()229     CalculateMatrixSignal& PostCalculateWorldMatrixSignal()
230     {
231         return *m_PostCalculateWorldMatrixSignal;
232     }
233 
234     //! @brief ワールドマトリクス計算後のシグナルを取得します。
235     //!
236     //! @sa CalculateMatrixSignal
PostCalculateWorldMatrixSignal()237     const CalculateMatrixSignal& PostCalculateWorldMatrixSignal() const
238     {
239         return *m_PostCalculateWorldMatrixSignal;
240     }
241 
242     //@}
243 
244 protected:
245     //----------------------------------------
246     //! @name コンストラクタ/デストラクタ
247     //@{
248 
249     //! @brief コンストラクタです。
250     TransformNode(
251         os::IAllocator* allocator,
252         ResTransformNode resObj,
253         const TransformNode::Description& description);
254 
255     //! @brief デストラクタです。
~TransformNode()256     virtual ~TransformNode()
257     {
258         SafeDestroy(m_PostCalculateWorldMatrixSignal);
259     }
260 
261     virtual Result Initialize(os::IAllocator* allocator);
262 
263     //@}
264 
265     //! @brief 親ノードの変換情報を継承した方向を計算します。
CalcInheritingDiretion(math::VEC3 & inheritingDirection,const math::VEC3 & direction)266     void CalcInheritingDiretion(
267         math::VEC3& inheritingDirection,
268         const math::VEC3 &direction) const
269     {
270         if (this->GetParent() == NULL)
271         {
272             inheritingDirection = direction;
273         }
274         else
275         {
276             const math::MTX34& parentWorldMatrix =  this->TrackbackWorldMatrix();
277             inheritingDirection.x =
278                 parentWorldMatrix.f._00 * direction.x +
279                 parentWorldMatrix.f._01 * direction.y +
280                 parentWorldMatrix.f._02 * direction.z;
281 
282             inheritingDirection.y =
283                 parentWorldMatrix.f._10 * direction.x +
284                 parentWorldMatrix.f._11 * direction.y +
285                 parentWorldMatrix.f._12 * direction.z;
286 
287             inheritingDirection.z =
288                 parentWorldMatrix.f._20 * direction.x +
289                 parentWorldMatrix.f._21 * direction.y +
290                 parentWorldMatrix.f._22 * direction.z;
291         }
292     }
293 
294 
295     //! @brief   Initialize() の実行に必要なメモリサイズを取得します。
296     //!
297     //! @details :private
GetMemorySizeForInitialize(os::MemorySizeCalculator * pSize,ResTransformNode resTransformNode,Description description)298     static void GetMemorySizeForInitialize(
299         os::MemorySizeCalculator* pSize,
300         ResTransformNode resTransformNode,
301         Description description)
302     {
303         NW_ASSERT(description.isFixedSizeMemory);
304 
305         SceneNode::GetMemorySizeForInitialize(pSize, resTransformNode, description);
306 
307         // TransformNode::CreateCallbacks
308         if (description.maxCallbacks == 0)
309         {
310             CalculateMatrixSignal::GetMemorySizeForInvalidateSignalInternal(pSize);
311         }
312         else
313         {
314             CalculateMatrixSignal::GetMemorySizeForFixedSizedSignalInternal(pSize, description.maxCallbacks);
315         }
316     }
317 
318 private:
319     //! @brief コールバック関数を生成します。
320     Result CreateCallbacks(os::IAllocator* allocator);
321 
322     CalculatedTransform m_Transform;
323     math::MTX34 m_WorldMatrix;
324     CalculatedTransform m_CalculatedTransform;
325 
326     mutable math::MTX34 m_InverseWorldMatrix;
327     mutable bool m_IsInverseWorldMatrixValid;
328 
329     CalculateMatrixSignal* m_PostCalculateWorldMatrixSignal;
330     bool m_IsBranchWorldMatrixCalculationEnabled;
331     Description m_Description;
332 };
333 
334 //----------------------------------------
335 NW_INLINE void
InheritTraversalResults()336 TransformNode::InheritTraversalResults()
337 {
338     SceneNode::InheritTraversalResults();
339 
340     SceneNode* parent = this->GetParent();
341     bit32 results = this->GetTraversalResults();
342 
343     if (this->Transform().IsEnabledFlags(CalculatedTransform::FLAG_IS_DIRTY))
344     {
345         results = ut::EnableFlag(results, SceneNode::FLAG_IS_DIRTY);
346     }
347     else if (parent== NULL)
348     {
349         results = ut::DisableFlag(results, SceneNode::FLAG_IS_DIRTY);
350     }
351     else if (parent->IsEnabledResults(SceneNode::FLAG_IS_DIRTY))
352     {
353         results = ut::EnableFlag(results, SceneNode::FLAG_IS_DIRTY);
354     }
355     else
356     {
357         results = ut::DisableFlag(results, SceneNode::FLAG_IS_DIRTY);
358     }
359 
360     this->SetTraversalResults(results);
361 }
362 
363 //----------------------------------------
364 NW_INLINE void
InheritTransformStates()365 TransformNode::InheritTransformStates()
366 {
367     this->InheritTraversalResults();
368 }
369 
370 
371 } // namespace gfx
372 } // namespace nw
373 
374 #endif // NW_GFX_TRANSFORMNODE_H_
375