/*---------------------------------------------------------------------------* Project: NintendoWare File: gfx_SceneHelper.h Copyright (C)2009-2010 Nintendo Co., Ltd./HAL Laboratory, Inc. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Revision: $ *---------------------------------------------------------------------------*/ #ifndef NW_GFX_SCENEHELPER_H_ #define NW_GFX_SCENEHELPER_H_ #include #include namespace nw { namespace gfx { //! @brief シーンオブジェクトが持つリソースから、シーンの親子関係を各ノードに設定するライブラリクラスです。 class SceneHelper { private: SceneHelper(); NW_DISALLOW_COPY_AND_ASSIGN(SceneHelper); public: //! @brief シーンツリーの参照構造を解決します。 //! //! @tparam TIterator シーンツリーが格納されるコレクションのイテレータです。 //! @param[in] begin 解決したいシーンノードのコレクションの先頭です。 //! @param[in] end 解決したいシーンノードのコレクションの終端です。 //! template static void ResolveReference(TIterator begin, TIterator end) { for (TIterator parent = begin; parent != end; ++parent) { for (TIterator child = begin; child != end; ++child) { NW_NULL_ASSERT(ut::DynamicCast(*child)); ResolveReferenceImpl(*parent, *child); } } } //! シーンツリーの参照解決の別インターフェースです。 template static void ResolveReference(const std::pair& range) { ResolveReference(range.first, range.second); } //! シーンツリーの参照解決の別インターフェースです。 template static void ResolveReference(TNode (&nodes)[TSize]) { ResolveReference(nodes, nodes + TSize); } //! シーンツリーの参照解決の別インターフェースです。 template static void ResolveReference(TNodeArray& nodes) { ResolveReference(nodes.begin(), nodes.end()); } //! @brief シーンノードの集合から、親がNULLのノードに対して処理を行います。 //! //! @tparam TIterator シーンノードの集合のイテレータです。 //! @tparam TFunction 親がNULLのシーンノードに行う処理です。 //! @param begin シーンノードのコレクションの先頭です。 //! @param end シーンノードのコレクションの終端です。 //! @param function シーンノードに行う処理です。 //! template static void ForeachRootNodes(TIterator begin, TIterator end, TFunction function) { for (TIterator iter = begin; iter != end; ++iter) { if ((*iter)->GetParent() == NULL) { function(*iter); } } } //---------------------------------------- //! @name 深度計算 //@{ //! @brief クリップ座標系での深度を計算します。 static float CalculateDepth( const math::VEC3& localPosition, const math::MTX34& worldMatrix, const Camera& camera) { math::VEC3 position; math::VEC3Transform(&position, &worldMatrix, &localPosition); math::VEC3Transform(&position, &camera.ViewMatrix(), &position); const math::MTX44& projection = camera.ProjectionMatrix(); float z = projection.f._20 * position.x + projection.f._21 * position.y + projection.f._22 * position.z + projection.f._23; float w = projection.f._30 * position.x + projection.f._31 * position.y + projection.f._32 * position.z + projection.f._33; // クリップ座標系の Z 深度は 0 ~ -w の範囲になるので、 // 0 ~ 1.0 の範囲になるように変換します。 return ut::Clamp(-z / w, 0.0f, 1.0f); } //! @brief クリップ座標系での深度を計算します。 static float CalculateDepth( const math::MTX34& worldMatrix, const Camera& camera) { math::VEC3 position(worldMatrix.GetColumn(3)); math::VEC3Transform(&position, &camera.ViewMatrix(), &position); const math::MTX44& projection = camera.ProjectionMatrix(); float z = projection.f._20 * position.x + projection.f._21 * position.y + projection.f._22 * position.z + projection.f._23; float w = projection.f._30 * position.x + projection.f._31 * position.y + projection.f._32 * position.z + projection.f._33; // クリップ座標系の Z 深度は 0 ~ -w の範囲になるので、 // 0 ~ 1.0 の範囲になるように変換します。 return ut::Clamp(-z / w, 0.0f, 1.0f); } //@} private: // シーンツリー解釈の内部実装。 static void ResolveReferenceImpl(SceneNode* parent, SceneNode* child); }; //! @brief シーンノードに子を取り付けるための関数オブジェクトです。 class AttachNode { public: //! @brief コンストラクタです。 //! //! @param[in] parent 取り付ける親ノードです。 AttachNode(nw::gfx::SceneNode* parent) : m_Parent(parent) {} //! @brief 親ノードに子を取り付けます。 //! //! @param[in] node 取り付けられるオブジェクトです。 template void operator() (TNode* node) { NW_POINTER_ASSERT(m_Parent); m_Parent->AttachChild(node); } private: nw::gfx::SceneNode* m_Parent; }; } // namespace gfx } // namespace nw #endif // NW_GFX_SCENEHELPER_H_