//------------------------------------------------------------------------------
// Lamp : Open source game middleware
// Copyright (C) 2004  Junpei Ohtani ( Email : junpee@users.sourceforge.jp )
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//------------------------------------------------------------------------------

/** @file
 * インフォメーションレンダラ実装
 * @author Junpee
 */

#include "LampBasic.h"
#include "Graphics/Renderer/InformationRenderer.h"
#include "Graphics/PrimitiveRenderer/PrimitiveRenderer.h"
#include "Graphics/PrimitiveRenderer/PrimitiveDrawRequestBuilder.h"
#include "Graphics/Scene/Scene.h"
#include "Graphics/SceneNode/SceneNodeManager.h"
#include "Graphics/Model/CharacterModel.h"
#include "Graphics/Mesh/Mesh.h"

namespace Lamp{

/// メッシュバウンディングカラー
const Color4c InformationRenderer::meshBoundingColor_ = Color4c(0, 255, 0, 64);
/// ボーンカラー
const Color4c InformationRenderer::boneColor_ = Color4c(0, 255, 255, 255);

//------------------------------------------------------------------------------
// 生成、破棄
//------------------------------------------------------------------------------
// コンストラクタ
InformationRenderer::InformationRenderer() : scene_(NULL), camera_(NULL),
	isDrawnGrid_(false), isDrawnAxis_(false), isDrawnMeshBounding_(false),
	isDrawnBone_(false){
	renderer_ = new PrimitiveRenderer;
}
//------------------------------------------------------------------------------
// デストラクタ
InformationRenderer::~InformationRenderer(){
	SafeDelete(renderer_);
}
//------------------------------------------------------------------------------
// レンダリング
//------------------------------------------------------------------------------
// レンダリング準備を行う
void InformationRenderer::renderingSetup(Scene* scene){
	Assert(scene != NULL);
	scene_ = scene;
	camera_ = scene_->getCurrentCamera();
	Assert(camera_ != NULL);
	// メッシュリストの取得
	if(isDrawnMeshBounding() || isDrawnBone()){
		scene_->getMeshList(&meshList_, camera_);
	}
	// グリッドの描画
	if(isDrawnGrid()){ setupGrid(); }
	// 軸の描画
	if(isDrawnAxis()){ setupAxis(); }
	// メッシュバウンディングの描画
	if(isDrawnMeshBounding()){ setupMeshBounding(); }
	// ボーンの描画
	if(isDrawnBone()){ setupBone(); }
	// メッシュリストのクリア
	meshList_.clear();
}
//------------------------------------------------------------------------------
// グリッドのセットアップ
void InformationRenderer::setupGrid(){
	renderer_->requestGrid(Vector3(100.f, 100.f, 100.f),
		Vector3::zero, Vector3::zero, Color4c::white, true);
}
//------------------------------------------------------------------------------
// 軸のセットアップ
void InformationRenderer::setupAxis(){
	SceneNodeManager* sceneNodeManager = scene_->getSceneNodeManager();
	int sceneNodeCount = sceneNodeManager->getCount();
	for(int i = 0; i < sceneNodeCount; i++){
		SceneNode* sceneNode = sceneNodeManager->get(i);
		if(!sceneNode->isGlobalEnabled()){ continue; }
		renderer_->requestAxis(sceneNode->getWorldMatrix(),
			Color4c::white, false);
	}
}
//------------------------------------------------------------------------------
// メッシュバウンディングのセットアップ
void InformationRenderer::setupMeshBounding(){
	int meshCount = meshList_.getCount();
	for(int i = 0; i < meshCount; i++){
		Mesh* mesh = meshList_[i];
		const Sphere& boundingSphere = mesh->getWorldBoundingSphere();
		float radius = boundingSphere.getRadius();
		renderer_->requestSphere(Vector3(radius, radius, radius),
			Vector3::zero, boundingSphere.getCenter(), meshBoundingColor_);
	}
}
//------------------------------------------------------------------------------
// ボーンのセットアップ
void InformationRenderer::setupBone(){
	/// キャラクタモデルリスト
	ArrayList<CharacterModel*> modelList_;
	int meshCount = meshList_.getCount();
	for(int i = 0; i < meshCount; i++){
		// キャラクタモデルかどうか
		CharacterModel* model = meshList_[i]->getParent()->castCharacterModel();
		if(model == NULL){ continue; }
		// すでにそのモデルを描画していないかチェック
		int modelCount = modelList_.getCount();
		for(int j = 0; j < modelCount; j++){
			if(modelList_[j] == model){
				model = NULL;
				break;
			}
		}
		if(model == NULL){ continue; }
		modelList_.add(model);
		PrimitiveDrawRequest primitive;
		PrimitiveDrawRequestBuilder::buildBone(&primitive, model);
		renderer_->request(primitive, model->getParent()->getWorldMatrix(),
			boneColor_, false);
	}
}
//------------------------------------------------------------------------------
// レンダリングを行う
void InformationRenderer::rendering(){
	Assert(scene_ != NULL);
	Assert(camera_ != NULL);
	renderer_->render(camera_);
}
//------------------------------------------------------------------------------
} // End of namespace Lamp
//------------------------------------------------------------------------------
