//------------------------------------------------------------------------------
// 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 "Geometry/Mesh/DeformedMeshGeometry.h"
#include "Geometry/System/IntersectionResult.h"

namespace Lamp{

//------------------------------------------------------------------------------
// 生成、破棄
//------------------------------------------------------------------------------
// コンストラクタ
DeformedMeshGeometry::DeformedMeshGeometry() : MeshGeometry(),
	boundingBox_(AxisAlignedBox::zero), boundingSphere_(Sphere::zero),
	triangles_(NULL), triangleCount_(0){
}
//------------------------------------------------------------------------------
// コピーコンストラクタ
DeformedMeshGeometry::DeformedMeshGeometry(const DeformedMeshGeometry& copy) :
	MeshGeometry(copy), boundingBox_(AxisAlignedBox::zero),
	boundingSphere_(Sphere::zero), triangles_(NULL), triangleCount_(0){
	copyDeformedMeshGeometryData(copy);
}
//------------------------------------------------------------------------------
// 代入コピー
const DeformedMeshGeometry& DeformedMeshGeometry::operator =(
	const DeformedMeshGeometry& copy){
	// 自分自身ならリターン
	if(this == &copy){ return *this; }
	MeshGeometry::operator =(copy);
	copyDeformedMeshGeometryData(copy);
	return *this;
}
//------------------------------------------------------------------------------
// 変形メッシュジオメトリデータのコピー
void DeformedMeshGeometry::copyDeformedMeshGeometryData(
	const DeformedMeshGeometry& copy){
	int triangleCount = copy.getTriangleCount();
	setTriangleCount(triangleCount);
	for(int i = 0; i < triangleCount; i++){
		setTriangle(i, copy.getTriangle(i));
	}
	setBoundingBox(copy.getBoundingBox());
	setBoundingSphere(copy.getBoundingSphere());
}
//------------------------------------------------------------------------------
// デストラクタ
DeformedMeshGeometry::~DeformedMeshGeometry(){
	SafeArrayDelete(triangles_);
}
//------------------------------------------------------------------------------
// 交差
//------------------------------------------------------------------------------
// 球交差
bool DeformedMeshGeometry::intersect(const Sphere& sphere) const{
	// バウンディング交差
	if(!intersectBounding(sphere)){ return false; }
	// メッシュ交差
	return intersectMesh(sphere);
}
//------------------------------------------------------------------------------
// 球交差
void DeformedMeshGeometry::intersect(
	IntersectionResult* result, const Sphere& sphere) const{
	// バウンディング交差
	if(!intersectBounding(sphere)){ return; }
	// メッシュ交差
	intersectMesh(result, sphere);
}
//------------------------------------------------------------------------------
// 球バウンディング交差
bool DeformedMeshGeometry::intersectBounding(const Sphere& sphere) const{
	// バウンディングスフィア
	if(!boundingSphere_.intersect(sphere)){ return false; }
	// バウンディングボックス
	if(!boundingBox_.intersect(sphere)){ return false; }
	return true;
}
//------------------------------------------------------------------------------
// 球メッシュ交差
bool DeformedMeshGeometry::intersectMesh(const Sphere& sphere) const{
	for(int i = 0; i < triangleCount_; i++){
		if(triangles_[i].intersect(sphere)){ return true; }
	}
	return false;
}
//------------------------------------------------------------------------------
// 球メッシュ交差
void DeformedMeshGeometry::intersectMesh(
	IntersectionResult* result, const Sphere& sphere) const{
	Intersection intersection;
	for(int i = 0; i < triangleCount_; i++){
		if(triangles_[i].intersect(&intersection, sphere)){
			result->add(intersection);
		}
	}
}
//------------------------------------------------------------------------------
// トライアングル
//------------------------------------------------------------------------------
// トライアングル数の設定
void DeformedMeshGeometry::setTriangleCount(int triangleCount){
	Assert(triangleCount >= 0);
	SafeArrayDelete(triangles_);
	triangleCount_ = triangleCount;
	if(triangleCount_ == 0){ return; }
	triangles_ = new Triangle[triangleCount_];
}
//------------------------------------------------------------------------------
// バウンディング
//------------------------------------------------------------------------------
// バウンディングの算出
void DeformedMeshGeometry::calculateBounding(){
	if(triangleCount_ == 0){ return; }

	// バウンディングボックス
	const Vector3& initializePosition = triangles_[0].getVertex(0);
	boundingBox_.set(initializePosition, initializePosition);
	for(int i = 0; i < triangleCount_; i++){
		const Triangle& triangle = triangles_[i];
		for(int j = 0; j < 3; j++){
			boundingBox_.merge(triangle.getVertex(j));
		}
	}

	// バウンディングスフィア
	boundingSphere_.set(boundingBox_.getCenter(), 0.f);
	for(int i = 0; i < triangleCount_; i++){
		const Triangle& triangle = triangles_[i];
		for(int j = 0; j < 3; j++){
			boundingSphere_.append(triangle.getVertex(j));
		}
	}
}
//------------------------------------------------------------------------------
} // End of namespace Lamp
//------------------------------------------------------------------------------
