1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     gfx_SceneHelper.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: $
16  *---------------------------------------------------------------------------*/
17 
18 
19 #ifndef NW_GFX_SCENEHELPER_H_
20 #define NW_GFX_SCENEHELPER_H_
21 
22 #include <nw/gfx/gfx_SceneNode.h>
23 #include <nw/ut/ut_MoveArray.h>
24 
25 namespace nw
26 {
27 namespace gfx
28 {
29 
30 //! @brief シーンオブジェクトが持つリソースから、シーンの親子関係を各ノードに設定するライブラリクラスです。
31 class SceneHelper
32 {
33 private:
34     SceneHelper();
35     NW_DISALLOW_COPY_AND_ASSIGN(SceneHelper);
36 
37 public:
38     //! @brief         シーンツリーの参照構造を解決します。
39     //!
40     //! @tparam        TIterator シーンツリーが格納されるコレクションのイテレータです。
41     //! @param[in]     begin 解決したいシーンノードのコレクションの先頭です。
42     //! @param[in]     end 解決したいシーンノードのコレクションの終端です。
43     //!
44     template<typename TIterator>
ResolveReference(TIterator begin,TIterator end)45     static void ResolveReference(TIterator begin, TIterator end)
46     {
47         for (TIterator parent = begin; parent != end; ++parent)
48         {
49             for (TIterator child = begin; child != end; ++child)
50             {
51                 NW_NULL_ASSERT(ut::DynamicCast<SceneNode*>(*child));
52                 ResolveReferenceImpl(*parent, *child);
53             }
54         }
55     }
56 
57     //! シーンツリーの参照解決の別インターフェースです。
58     template<typename TIterator>
ResolveReference(const std::pair<TIterator,TIterator> & range)59     static void ResolveReference(const std::pair<TIterator, TIterator>& range)
60     {
61         ResolveReference<TIterator>(range.first, range.second);
62     }
63 
64     //! シーンツリーの参照解決の別インターフェースです。
65     template<typename TNode, int TSize>
ResolveReference(TNode (& nodes)[TSize])66     static void ResolveReference(TNode (&nodes)[TSize])
67     {
68         ResolveReference<TNode*>(nodes, nodes + TSize);
69     }
70 
71     //! シーンツリーの参照解決の別インターフェースです。
72     template<typename TNodeArray>
ResolveReference(TNodeArray & nodes)73     static void ResolveReference(TNodeArray& nodes)
74     {
75         ResolveReference<TNodeArray::iterator>(nodes.begin(), nodes.end());
76     }
77 
78     //! @brief      シーンノードの集合から、親がNULLのノードに対して処理を行います。
79     //!
80     //! @tparam     TIterator  シーンノードの集合のイテレータです。
81     //! @tparam     TFunction  親がNULLのシーンノードに行う処理です。
82     //! @param      begin      シーンノードのコレクションの先頭です。
83     //! @param      end        シーンノードのコレクションの終端です。
84     //! @param      function   シーンノードに行う処理です。
85     //!
86     template <typename TIterator, typename TFunction>
87     static void
ForeachRootNodes(TIterator begin,TIterator end,TFunction function)88     ForeachRootNodes(TIterator begin, TIterator end, TFunction function)
89     {
90         for (TIterator iter = begin; iter != end; ++iter)
91         {
92             if ((*iter)->GetParent() == NULL)
93             {
94                 function(*iter);
95             }
96         }
97     }
98 
99     //----------------------------------------
100     //! @name 深度計算
101     //@{
102 
103     //! @brief クリップ座標系での深度を計算します。
CalculateDepth(const math::VEC3 & localPosition,const math::MTX34 & worldMatrix,const Camera & camera)104     static float CalculateDepth(
105         const math::VEC3& localPosition,
106         const math::MTX34& worldMatrix,
107         const Camera& camera)
108     {
109         math::VEC3 position;
110         math::VEC3Transform(&position, &worldMatrix, &localPosition);
111         math::VEC3Transform(&position, &camera.ViewMatrix(), &position);
112         const math::MTX44& projection = camera.ProjectionMatrix();
113         float z =
114             projection.f._20 * position.x +
115             projection.f._21 * position.y +
116             projection.f._22 * position.z +
117             projection.f._23;
118         float w =
119             projection.f._30 * position.x +
120             projection.f._31 * position.y +
121             projection.f._32 * position.z +
122             projection.f._33;
123         // クリップ座標系の Z 深度は 0 ~ -w の範囲になるので、
124         // 0 ~ 1.0 の範囲になるように変換します。
125         return ut::Clamp(-z / w, 0.0f, 1.0f);
126     }
127 
128     //! @brief クリップ座標系での深度を計算します。
CalculateDepth(const math::MTX34 & worldMatrix,const Camera & camera)129     static float CalculateDepth(
130         const math::MTX34& worldMatrix,
131         const Camera& camera)
132     {
133         math::VEC3 position(worldMatrix.GetColumn(3));
134         math::VEC3Transform(&position, &camera.ViewMatrix(), &position);
135         const math::MTX44& projection = camera.ProjectionMatrix();
136         float z =
137             projection.f._20 * position.x +
138             projection.f._21 * position.y +
139             projection.f._22 * position.z +
140             projection.f._23;
141         float w =
142             projection.f._30 * position.x +
143             projection.f._31 * position.y +
144             projection.f._32 * position.z +
145             projection.f._33;
146         // クリップ座標系の Z 深度は 0 ~ -w の範囲になるので、
147         // 0 ~ 1.0 の範囲になるように変換します。
148         return ut::Clamp(-z / w, 0.0f, 1.0f);
149     }
150 
151     //@}
152 
153 private:
154     // シーンツリー解釈の内部実装。
155     static void ResolveReferenceImpl(SceneNode* parent, SceneNode* child);
156 };
157 
158 //! @brief  シーンノードに子を取り付けるための関数オブジェクトです。
159 class AttachNode
160 {
161 public:
162     //! @brief コンストラクタです。
163     //!
164     //! @param[in] parent 取り付ける親ノードです。
AttachNode(nw::gfx::SceneNode * parent)165     AttachNode(nw::gfx::SceneNode* parent)
166     : m_Parent(parent)
167     {}
168 
169     //! @brief 親ノードに子を取り付けます。
170     //!
171     //! @param[in] node 取り付けられるオブジェクトです。
172     template <typename TNode>
operator()173     void operator() (TNode* node)
174     {
175         NW_POINTER_ASSERT(m_Parent);
176         m_Parent->AttachChild(node);
177     }
178 
179 private:
180     nw::gfx::SceneNode* m_Parent;
181 };
182 
183 } // namespace gfx
184 } // namespace nw
185 
186 #endif // NW_GFX_SCENEHELPER_H_
187