//------------------------------------------------------------------------------
// 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 "Collision/Renderer/CollisionRenderer.h"
#include "Graphics/PrimitiveRenderer/PrimitiveRenderer.h"
#include "Collision/System/CollisionScene.h"
#include "Collision/System/CollisionNode.h"
#include "Collision/Leaf/StaticSphereCollision.h"
#include "Collision/Leaf/StaticDeformedMeshCollision.h"

namespace Lamp{

//------------------------------------------------------------------------------
// コンストラクタ
CollisionRenderer::CollisionRenderer() : scene_(NULL), camera_(NULL),
	isDrawnNode_(true), isDrawnLeaf_(true){
	renderer_ = new PrimitiveRenderer;
}
//------------------------------------------------------------------------------
// デストラクタ
CollisionRenderer::~CollisionRenderer(){
	SafeDelete(renderer_);
}
//------------------------------------------------------------------------------
// レンダリング準備
//------------------------------------------------------------------------------
// レンダリング準備を行う
void CollisionRenderer::renderingSetup(CollisionScene* scene, Camera* camera){
	scene_ = scene;
	camera_ = camera;
	Assert((scene_ != NULL) && (camera_ != NULL));
	// ノードの描画
	if(isDrawnNode()){
		int nodeCount = scene_->getNodeCount();
		for(int i = 0; i < nodeCount; i++){
			CollisionNode* node = scene_->getNode(i);
			if(!node->isGlobalEnabled()){ continue; }
			renderer_->requestAxis(node->getWorldMatrix(),
				Color4c::white, false);
		}
	}
	// リーフの描画
	if(isDrawnLeaf()){
		int leafCount = scene_->getLeafCount();
		for(int i = 0; i < leafCount; i++){
			CollisionLeaf* leaf = scene_->getLeaf(i);
			if(!leaf->isGlobalEnabled()){ continue; }
			if(leaf->isStaticSphereCollision()){
				setupStaticSphereCollision(leaf->castStaticSphereCollision());
			}else if(leaf->isStaticDeformedMeshCollision()){
				setupStaticDeformedMeshCollision(
					leaf->castStaticDeformedMeshCollision());
			}
		}
	}
}
//------------------------------------------------------------------------------
// 静的球コリジョンのセットアップ
void CollisionRenderer::setupStaticSphereCollision(
	StaticSphereCollision* sphereCollision){
	const Sphere& sphere = sphereCollision->getWorldSphere();
	float radius = sphere.getRadius();
	Vector3 scale(radius, radius, radius);
	renderer_->requestSphere(scale, Vector3::zero, sphere.getCenter(),
		Color4c(255, 255, 128, 128), true);
 }
//------------------------------------------------------------------------------
// 静的変形メッシュコリジョンのセットアップ
void CollisionRenderer::setupStaticDeformedMeshCollision(
	StaticDeformedMeshCollision* meshCollision){
	const DeformedMeshGeometry& geometry = meshCollision->getWorldMesh();
	// バウンディングスフィア
	const Sphere& boundingSphere = geometry.getBoundingSphere();
	float radius = boundingSphere.getRadius();
	renderer_->requestSphere(Vector3(radius, radius, radius),
		Vector3::zero, boundingSphere.getCenter(),
		Color4c(128, 255, 128, 64), true);

	// バウンディングボックス
	const AxisAlignedBox& boundingBox = geometry.getBoundingBox();
	renderer_->requestBox(boundingBox.getSize(), Vector3::zero,
		boundingBox.getCenter(), Color4c(128, 255, 128, 64), true);

	// メッシュ
	int triangleCount = geometry.getTriangleCount();
	int vertexCount = triangleCount * 6;
	Vector3* positions = new Vector3[vertexCount];
	for(int i = 0; i < triangleCount; i++){
		const Triangle& triangle = geometry.getTriangle(i);
		int offset = i * 6;
		positions[offset + 0] = triangle.getVertex(0);
		positions[offset + 1] = triangle.getVertex(1);
		positions[offset + 2] = triangle.getVertex(1);
		positions[offset + 3] = triangle.getVertex(2);
		positions[offset + 4] = triangle.getVertex(2);
		positions[offset + 5] = triangle.getVertex(0);
	}
	renderer_->requestLine(vertexCount, positions, Matrix34::unit,
		Color4c(255, 255, 128, 64), true);
	SafeArrayDelete(positions);
}
//------------------------------------------------------------------------------
// レンダリング
//------------------------------------------------------------------------------
// レンダリングを行う
void CollisionRenderer::rendering(){
	Assert((scene_ != NULL) && (camera_ != NULL));
	renderer_->render(camera_);
}
//------------------------------------------------------------------------------
} // End of namespace Lamp
//------------------------------------------------------------------------------
