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