/*---------------------------------------------------------------------------* Project: NintendoWare File: gfx_SceneUpdateHelper.h Copyright (C)2009-2011 Nintendo/HAL Laboratory, Inc. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo and/or its licensed developers and are protected by national and international copyright laws. 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. The content herein is highly confidential and should be handled accordingly. $Revision: $ *---------------------------------------------------------------------------*/ #ifndef NW_GFX_SCENEUPDATEHELPER_H_ #define NW_GFX_SCENEUPDATEHELPER_H_ #include #include #include #include namespace nw { namespace gfx { //--------------------------------------------------------------------------- //! @brief シーン更新の手助けをするライブラリクラスです。 //--------------------------------------------------------------------------- class SceneUpdateHelper { public: //--------------------------------------------------------------------------- //! @brief カメラの視界に基づいてシーンを更新し、描画キューを構築する関数オブジェクトです。 //! //! @tparam EnqueueModelMesh モデルをレンダーキューに積むための関数オブジェクトの型です。 //! @tparam EnqueueSkeletalModelFunctor スケルタルモデルをレンダーキューに積むための関数オブジェクトの型です。 //! @tparam IsVisibleModel 表示するモデルを識別するための関数オブジェクトの型です。 //--------------------------------------------------------------------------- template< typename EnqueueModelMesh, typename EnqueueSkeletalModelMesh, typename IsVisibleModel> class SubmitViewFunctor : public std::unary_function { public: //! @brief コンストラクタです。 //! //! @param[in] skeletonUpdater //! @param[in] billboardUpdater //! @param[in] renderQueue 描画対象となる要素を集めたキューです。 //! @param[in] camera カメラです。 //! @param[in] layerId 描画要素のソート時に最優先に区分される ID です。レイヤーやビューポートの描画を制御するのに用います。 //! @param[in] particleLayerId パーティクル描画用の layerId です。 //! @param[in] isVisibleModel 表示するモデルを識別するための関数オブジェクトです。 //! SubmitViewFunctor( SkeletonUpdater* skeletonUpdater, BillboardUpdater* billboardUpdater, RenderQueue* renderQueue, const Camera* camera, u8 layerId, u8 particleLayerId, IsVisibleModel* isVisibleModel) : m_SkeletonUpdater(skeletonUpdater), m_BillboardUpdater(billboardUpdater), m_RenderQueue(renderQueue), m_Camera(camera), m_LayerId(layerId), m_ParticleLayerId(particleLayerId), m_IsVisibleModel(isVisibleModel) {} //! @brief カメラの視界に基づいてシーンを更新し、描画キューを構築します。 //! //! @param[in] model 描画対象となるモデルです。 //! void operator() (Model* model) { // スケルタルモデルの更新を行います。 SkeletalModel* skeletalModel = ut::DynamicCast(model); if (skeletalModel) { Skeleton* skeleton = skeletalModel->GetSkeleton(); // 必ず Skeleton の更新フラグを false に設定します。 skeleton->SetUpdated(false); } if (!m_IsVisibleModel->IsVisible(model)) { return; } if (skeletalModel) { if (!skeletalModel->IsSharingSkeleton()) { this->m_SkeletonUpdater->UpdateView( skeletalModel->GetSkeleton(), *this->m_BillboardUpdater, *this->m_Camera); } const Skeleton* skeleton = skeletalModel->GetSkeleton(); ResSkeleton resSkeleton = skeleton->GetResSkeleton(); bool isModelCoordinate = ut::CheckFlag(resSkeleton.GetFlags(), ResSkeletonData::FLAG_MODEL_COORDINATE); model->UpdateModelViewMatrixAndNormalMatrix(this->m_Camera->ViewMatrix(), isModelCoordinate); u8 meshLayerId = m_LayerId | model->GetLayerId(); // ZSort 用の深度を計算して、レンダーキューにメッシュを積みます。 gfx::ResMeshArray meshs = skeletalModel->GetResMeshes(); std::for_each( meshs.begin(), meshs.end(), EnqueueSkeletalModelMesh(this->m_RenderQueue, skeletalModel, meshLayerId, *this->m_Camera)); } else { model->UpdateModelViewMatrixAndNormalMatrix(this->m_Camera->ViewMatrix(), false); u8 meshLayerId = ut::IsTypeOf(model) ? this->m_ParticleLayerId : this->m_LayerId; meshLayerId |= model->GetLayerId(); // ZSort 用の深度を計算して、レンダーキューにメッシュを積みます。 gfx::ResMeshArray meshs = model->GetResMeshes(); std::for_each( meshs.begin(), meshs.end(), EnqueueModelMesh(this->m_RenderQueue, model, meshLayerId, *this->m_Camera)); } } private: SkeletonUpdater* m_SkeletonUpdater; BillboardUpdater* m_BillboardUpdater; RenderQueue* m_RenderQueue; const Camera* m_Camera; u8 m_LayerId; u8 m_ParticleLayerId; IsVisibleModel* m_IsVisibleModel; }; //! @brief カメラの視界に基づいてシーンを更新し、描画キューを構築します。 //! //! @tparam IsVisibleModelFunctor 表示するモデルを識別するための関数オブジェクトの型です。 //! @param[in] skeletonUpdater スケルトンアップデータです。 //! @param[in] billboardUpdater ビルボードアップデータです。 //! @param[in] renderQueue 描画対象となる要素を集めたキューです。 //! @param[in] sceneContext シーンコンテキストです。 //! @param[in] camera カメラです。 //! @param[in] layerId 描画要素のソート時に最優先に区分される ID です。レイヤーやビューポートの描画を制御するのに用います。 //! @param[in] particleLayerId パーティクル描画用の layerId です。 //! @param[in] isVisibleModel 表示するモデルを識別するための関数オブジェクトです。 //! @param[in] renderSortMode 描画ソートモードです。 //! template static void SubmitView( SkeletonUpdater* skeletonUpdater, BillboardUpdater* billboardUpdater, RenderQueue* renderQueue, SceneContext* sceneContext, const Camera& camera, u8 layerId, u8 particleLayerId, ISceneUpdater::RenderSortMode renderSortMode, ISceneUpdater::DepthSortMode depthSortMode, IsVisibleModelFunctor* isVisibleModel) { NW_NULL_ASSERT(sceneContext); if (depthSortMode == ISceneUpdater::SORT_DEPTH_OF_TRANSLUCENT_MESH) { // 半透明のメッシュのみ深度計算を行います。 // 不透明などのメッシュは深度によるソートがされなくなりますが、 // 深度計算分のCPUの処理負荷を削減します。 typedef SubmitViewFunctor< RenderQueue::FastEnqueueModelFunctor, RenderQueue::FastEnqueueSkeletalModelFunctor, IsVisibleModelFunctor> FastMeshBaseSubmitViewFunctor; typedef SubmitViewFunctor< RenderQueue::EnqueueModelTranslucentModelBaseFunctor, RenderQueue::EnqueueSkeletalModelTranslucentModelBaseFunctor, IsVisibleModelFunctor> FastTranslucentModelBaseSubmitViewFunctor; if (renderSortMode == ISceneUpdater::OPAQUE_MESH_BASE_AND_TRANSLUCENT_MODEL_BASE_SORT) { std::for_each( sceneContext->GetModelsBegin(), sceneContext->GetModelsEnd(), FastTranslucentModelBaseSubmitViewFunctor( skeletonUpdater, billboardUpdater, renderQueue, &camera, layerId, particleLayerId, isVisibleModel)); } else { std::for_each( sceneContext->GetModelsBegin(), sceneContext->GetModelsEnd(), FastMeshBaseSubmitViewFunctor( skeletonUpdater, billboardUpdater, renderQueue, &camera, layerId, particleLayerId, isVisibleModel)); } } else { // すべてのメッシュの深度計算を行います。 typedef SubmitViewFunctor< RenderQueue::EnqueueModelFunctor, RenderQueue::EnqueueSkeletalModelFunctor, IsVisibleModelFunctor> MeshBaseSubmitViewFunctor; typedef SubmitViewFunctor< RenderQueue::EnqueueModelTranslucentModelBaseFunctor, RenderQueue::EnqueueSkeletalModelTranslucentModelBaseFunctor, IsVisibleModelFunctor> TranslucentModelBaseSubmitViewFunctor; if (renderSortMode == ISceneUpdater::OPAQUE_MESH_BASE_AND_TRANSLUCENT_MODEL_BASE_SORT) { std::for_each( sceneContext->GetModelsBegin(), sceneContext->GetModelsEnd(), TranslucentModelBaseSubmitViewFunctor( skeletonUpdater, billboardUpdater, renderQueue, &camera, layerId, particleLayerId, isVisibleModel)); } else { std::for_each( sceneContext->GetModelsBegin(), sceneContext->GetModelsEnd(), MeshBaseSubmitViewFunctor( skeletonUpdater, billboardUpdater, renderQueue, &camera, layerId, particleLayerId, isVisibleModel)); } } } private: SceneUpdateHelper() {} ~SceneUpdateHelper() {} }; } // namespace gfx } // namespace nw #endif // NW_GFX_SCENEUPDATEHELPER_H_