//------------------------------------------------------------------------------
// 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
 */

#ifndef ORIENTED_BOX_H_
#define ORIENTED_BOX_H_

#include <Core/Primitive/Vector3.h>
#include <Core/Primitive/Matrix33.h>
#include <Core/Primitive/Matrix34.h>
#include <Core/Primitive/Matrix44.h>

namespace Lamp{

class AxisAlignedBox;
class Capsule;
class Cone;
class Line;
class Plane;
class Ray;
class Segment;
class Sphere;
class Triangle;

//------------------------------------------------------------------------------
/**
 * 指向性ボックス
 *
 * このクラスは継承しないで下さい。
 */
class OrientedBox{
public:
	//--------------------------------------------------------------------------
	// 定数
	//--------------------------------------------------------------------------
	/// ゼロボックス
	static const OrientedBox zero;

	/// 単位ボックス
	static const OrientedBox unit;

	//--------------------------------------------------------------------------
	// コンストラクタ
	//--------------------------------------------------------------------------
	/**
	 * コンストラクタ
	 *
	 * このコンストラクタは初期値の設定を行わないため値は不定です。
	 */
	inline OrientedBox(){}

	/**
	 * コンストラクタ
	 * @param rotationMatrix 回転行列の初期値
	 * @param center 中心の初期値
	 * @param extent 大きさの初期値
	 */
	inline OrientedBox(const Matrix33& rotationMatrix,
		const Vector3& center, const Vector3& extent) :
		rotationMatrix_(rotationMatrix), center_(center), extent_(extent){
		Assert((extent_.x >= 0.f) && (extent_.y >= 0.f) && (extent_.z >= 0.f));
	}

	/**
	 * コンストラクタ
	 * @param rotation00 回転行列のm00初期値
	 * @param rotation01 回転行列のm01初期値
	 * @param rotation02 回転行列のm02初期値
	 * @param rotation10 回転行列のm10初期値
	 * @param rotation11 回転行列のm11初期値
	 * @param rotation12 回転行列のm12初期値
	 * @param rotation20 回転行列のm20初期値
	 * @param rotation21 回転行列のm21初期値
	 * @param rotation22 回転行列のm22初期値
	 * @param centerX 中心Xの初期値
	 * @param centerY 中心Yの初期値
	 * @param centerZ 中心Zの初期値
	 * @param extentX 大きさXの初期値
	 * @param extentY 大きさYの初期値
	 * @param extentZ 大きさZの初期値
	 */
	inline OrientedBox(
		float rotation00, float rotation01, float rotation02,
		float rotation10, float rotation11, float rotation12,
		float rotation20, float rotation21, float rotation22,
		float centerX, float centerY, float centerZ,
		float extentX, float extentY, float extentZ) :
		rotationMatrix_(rotation00, rotation01, rotation02,
			rotation10, rotation11, rotation12,
			rotation20, rotation21, rotation22),
		center_(centerX, centerY, centerZ),
		extent_(extentX, extentY, extentZ){
		Assert((extent_.x >= 0.f) && (extent_.y >= 0.f) && (extent_.z >= 0.f));
	}

	/**
	 * コンストラクタ
	 * @param source 初期値配列
	 */
	inline explicit OrientedBox(const float* const source) :
		rotationMatrix_(source[0], source[1], source[2],
			source[3], source[4], source[5],
			source[6], source[7], source[8]),
		center_(source[9], source[10], source[11]),
		extent_(source[12], source[13], source[14]){
		Assert((extent_.x >= 0.f) && (extent_.y >= 0.f) && (extent_.z >= 0.f));
	}

	//--------------------------------------------------------------------------
	// 値の設定
	//--------------------------------------------------------------------------
	/**
	 * 値の設定
	 * @param rotationMatrix 設定する回転行列
	 * @param center 設定する中心
	 * @param extent 設定する大きさ
	 */
	inline void set(const Matrix33& rotationMatrix,
		const Vector3& center, const Vector3& extent){
		rotationMatrix_ = rotationMatrix;
		center_ = center;
		extent_ = extent;
		Assert((extent_.x >= 0.f) && (extent_.y >= 0.f) && (extent_.z >= 0.f));
	}

	/**
	 * 値の設定
	 * @param rotation00 設定する回転行列のm00
	 * @param rotation01 設定する回転行列のm01
	 * @param rotation02 設定する回転行列のm02
	 * @param rotation10 設定する回転行列のm10
	 * @param rotation11 設定する回転行列のm11
	 * @param rotation12 設定する回転行列のm12
	 * @param rotation20 設定する回転行列のm20
	 * @param rotation21 設定する回転行列のm21
	 * @param rotation22 設定する回転行列のm22
	 * @param centerX 設定する中心X
	 * @param centerY 設定する中心Y
	 * @param centerZ 設定する中心Z
	 * @param extentX 設定する大きさX
	 * @param extentY 設定する大きさY
	 * @param extentZ 設定する大きさZ
	 */
	inline void set(
		float rotation00, float rotation01, float rotation02,
		float rotation10, float rotation11, float rotation12,
		float rotation20, float rotation21, float rotation22,
		float centerX, float centerY, float centerZ,
		float extentX, float extentY, float extentZ){
		rotationMatrix_.set(rotation00, rotation01, rotation02,
			rotation10, rotation11, rotation12,
			rotation20, rotation21, rotation22);
		center_.set(centerX, centerY, centerZ);
		extent_.set(extentX, extentY, extentZ);
		Assert((extent_.x >= 0.f) && (extent_.y >= 0.f) && (extent_.z >= 0.f));
	}

	/**
	 * 値の設定
	 * @param source 設定値配列
	 */
	inline void set(const float* const source){
		rotationMatrix_.set(source[0], source[1], source[2],
			source[3], source[4], source[5],
			source[6], source[7], source[8]);
		center_.set(source[9], source[10], source[11]);
		extent_.set(source[12], source[13], source[14]);
		Assert((extent_.x >= 0.f) && (extent_.y >= 0.f) && (extent_.z >= 0.f));
	}

	//--------------------------------------------------------------------------
	/**
	 * 回転行列の設定
	 * @param rotationMatrix 回転行列
	 */
	inline void setRotationMatrix(const Matrix33& rotationMatrix){
		rotationMatrix_ = rotationMatrix;
	}

	/**
	 * XYZ回転の設定
	 * @param rotationXYZ XYZ回転
	 */
	inline void setRotationXYZ(const Vector3 rotationXYZ){
		rotationMatrix_.setRotationXYZ(rotationXYZ);
	}

	/**
	 * 四元数回転の設定
	 * @param rotationQuaternion 四元数回転
	 */
	inline void setRotationQuaternion(const Quaternion& rotationQuaternion){
		rotationMatrix_.setRotationQuaternion(rotationQuaternion);
	}

	//--------------------------------------------------------------------------
	/**
	 * 中心の設定
	 * @param center 中心
	 */
	inline void setCenter(const Vector3& center){ center_ = center; }

	//--------------------------------------------------------------------------
	/**
	 * 大きさの設定
	 * @param extent 大きさ
	 */
	inline void setExtent(const Vector3& extent){
		extent_ = extent;
		Assert((extent_.x >= 0.f) && (extent_.y >= 0.f) && (extent_.z >= 0.f));
	}

	//--------------------------------------------------------------------------
	// 値の取得
	//--------------------------------------------------------------------------
	/**
	 * 回転行列の取得
	 * @return 回転行列
	 */
	inline const Matrix33& getRotationMatrix() const{ return rotationMatrix_; }

	/**
	 * 中心の取得
	 * @return 中心
	 */
	inline const Vector3& getCenter() const{ return center_; }

	/**
	 * 大きさの取得
	 * @return 大きさ
	 */
	inline const Vector3& getExtent() const{ return extent_; }

	/**
	 * サイズの取得
	 * @return サイズ
	 */
	inline Vector3 getSize() const{ return (extent_ * 2.f); }

	//--------------------------------------------------------------------------
	/**
	 * 軸の取得
	 * @param index 軸インデックス
	 * @return 軸ベクトル
	 */
	inline Vector3 getAxis(int index) const{
		Assert((index >= 0) && (index < 3));
		return Vector3(rotationMatrix_.m[index][0],
			rotationMatrix_.m[index][1], rotationMatrix_.m[index][2]);
	}

	/**
	 * X軸の取得
	 * @return X軸ベクトル
	 */
	inline Vector3 getAxisX() const{
		return Vector3(
			rotationMatrix_.m00, rotationMatrix_.m01, rotationMatrix_.m02);
	}

	/**
	 * Y軸の取得
	 * @return Y軸ベクトル
	 */
	inline Vector3 getAxisY() const{
		return Vector3(
			rotationMatrix_.m10, rotationMatrix_.m11, rotationMatrix_.m12);
	}

	/**
	 * Z軸の取得
	 * @return X軸ベクトル
	 */
	inline Vector3 getAxisZ() const{
		return Vector3(
			rotationMatrix_.m20, rotationMatrix_.m21, rotationMatrix_.m22);
	}

	//--------------------------------------------------------------------------
	/**
	 * 大きさを適用した軸の取得
	 * @param index 軸インデックス
	 * @return 大きさを適用した軸ベクトル
	 */
	inline Vector3 getExtendedAxis(int index) const{
		Assert((index >= 0) && (index < 3));
		float extent = extent_.array[index];
		return Vector3(rotationMatrix_.m[index][0] * extent,
			rotationMatrix_.m[index][1] * extent,
			rotationMatrix_.m[index][2] * extent);
	}

	/**
	 * 大きさを適用したX軸の取得
	 * @return 大きさを適用したX軸ベクトル
	 */
	inline Vector3 getExtendedAxisX() const{
		return Vector3(rotationMatrix_.m00 * extent_.x,
			rotationMatrix_.m01 * extent_.x, rotationMatrix_.m02 * extent_.x);
	}

	/**
	 * 大きさを適用したY軸の取得
	 * @return 大きさを適用したY軸ベクトル
	 */
	inline Vector3 getExtendedAxisY() const{
		return Vector3(rotationMatrix_.m10 * extent_.y,
			rotationMatrix_.m11 * extent_.y, rotationMatrix_.m12 * extent_.y);
	}

	/**
	 * 大きさを適用したZ軸の取得
	 * @return 大きさを適用したX軸ベクトル
	 */
	inline Vector3 getExtendedAxisZ() const{
		return Vector3(rotationMatrix_.m20 * extent_.z,
			rotationMatrix_.m21 * extent_.z, rotationMatrix_.m22 * extent_.z);
	}

	//--------------------------------------------------------------------------
	/**
	 * 実効直径の取得
	 * @param direction 実効直径を測る方向
	 * @return 実効直径
	 */
	inline float getEffectiveDiameter(const Vector3& direction) const{
		return (Math::abs(direction.dotProduct(getExtendedAxisX())) +
			Math::abs(direction.dotProduct(getExtendedAxisY())) +
			Math::abs(direction.dotProduct(getExtendedAxisZ())));
	}

	/**
	 * 実効半径の取得
	 * @param direction 実効直径を測る方向
	 * @return 実効半径
	 */
	inline float getEffectiveRadius(const Vector3& direction) const{
		return getEffectiveDiameter(direction) * 0.5f;
	}

	//--------------------------------------------------------------------------
	/**
	 * コーナーの取得
	 *
	 * 以下の図のインデックスに沿ってコーナーを取得します。
	 * 0が中心で4が大きさです。
	 * <pre>
	 *     y+
	 *     |
	 *     1----2
	 *    /|   /|
	 *   5-+--4 |
	 *   | 0--+-3-- x+
	 *   |/   |/
	 *   6----7
	 *  /
	 * z+
	 * </pre>
	 * @param index インデックス
	 * @return コーナー
	 */
	inline Vector3 getCorner(int index) const{
		Assert((index >= 0) && (index < 8));
		Vector3 axisX = getExtendedAxisX();
		Vector3 axisY = getExtendedAxisY();
		Vector3 axisZ = getExtendedAxisZ();
		if(index == 0){
			return center_ - axisX - axisY - axisZ;
		}else if(index == 1){
			return center_ - axisX + axisY - axisZ;
		}else if(index == 2){
			return center_ + axisX + axisY - axisZ;
		}else if(index == 3){
			return center_ + axisX - axisY - axisZ;
		}else if(index == 4){
			return center_ + axisX + axisY + axisZ;
		}else if(index == 5){
			return center_ - axisX + axisY + axisZ;
		}else if(index == 6){
			return center_ - axisX - axisY + axisZ;
		}else if(index == 7){
			return center_ + axisX - axisY + axisZ;
		}
		ErrorOut("OrientedBox::getCorner() Out of index");
		return center_;
	}

	/**
	 * コーナー配列の取得
	 *
	 * 以下の図のインデックスに沿ってコーナーを取得します。
	 * 0が中心で4が大きさです。
	 * <pre>
	 *     y+
	 *     |
	 *     1----2
	 *    /|   /|
	 *   5-+--4 |
	 *   | 0--+-3-- x+
	 *   |/   |/
	 *   6----7
	 *  /
	 * z+
	 * </pre>
	 * @param corner [out] コーナー配列
	 */
	inline void getCornerArray(Vector3 corner[8]) const{
		const Matrix33& matrix = rotationMatrix_;
		Vector3 axisX = getExtendedAxisX();
		Vector3 axisY = getExtendedAxisY();
		Vector3 axisZ = getExtendedAxisZ();
		corner[0] = center_ - axisX - axisY - axisZ;
		corner[1] = center_ - axisX + axisY - axisZ;
		corner[2] = center_ + axisX + axisY - axisZ;
		corner[3] = center_ + axisX - axisY - axisZ;
		corner[4] = center_ + axisX + axisY + axisZ;
		corner[5] = center_ - axisX + axisY + axisZ;
		corner[6] = center_ - axisX - axisY + axisZ;
		corner[7] = center_ + axisX - axisY + axisZ;
	}

	//--------------------------------------------------------------------------
	// ボックス演算
	//--------------------------------------------------------------------------
	/**
	 * ゼロボックスかどうか
	 * @return ゼロボックスならtrueを返す
	 */
	inline bool isZero() const{
		return extent_.epsilonEquals(Vector3::zero, Math::epsilon);
	}

	/**
	 * 単位ボックスかどうか
	 * @return 単位ボックスならtrueを返す
	 */
	inline bool isUnit() const{
		return extent_.epsilonEquals(Vector3(0.5f, 0.5f, 0.5f), Math::epsilon);
	}

	//--------------------------------------------------------------------------
	// トランスフォーム
	//--------------------------------------------------------------------------
	/**
	 * トランスフォーム
	 * @param matrix 乗算する行列
	 * @return 変換後の指向性ボックス
	 */
	inline OrientedBox transform(const Matrix33& matrix) const{
		OrientedBox result;
		result.rotationMatrix_ = matrix * rotationMatrix_;
		result.center_ = matrix * center_;
		result.extent_ = extent_;
		return result;
	}

	/**
	 * トランスフォーム
	 * @param matrix 乗算する行列
	 * @return 変換後の指向性ボックス
	 */
	inline OrientedBox transform(const Matrix34& matrix) const{
		OrientedBox result;
		Matrix33 matrix33;
		matrix33.set(matrix);
		result.rotationMatrix_ = matrix33 * rotationMatrix_;
		result.center_ = matrix * center_;
		result.extent_ = extent_;
		return result;
	}

	/**
	 * トランスフォーム
	 * @param matrix 乗算する行列
	 * @return 変換後の指向性ボックス
	 */
	inline OrientedBox transform(const Matrix44& matrix) const{
		OrientedBox result;
		Matrix33 matrix33;
		matrix33.set(matrix);
		result.rotationMatrix_ = matrix33 * rotationMatrix_;
		result.center_ = matrix * center_;
		result.extent_ = extent_;
		return result;
	}

	//--------------------------------------------------------------------------
	/**
	 * スケール有りトランスフォーム
	 * @param matrix 乗算する行列
	 * @return 変換後の軸沿いボックス
	 */
	AxisAlignedBox scaledTransform(const Matrix33& matrix) const;

	/**
	 * スケール有りトランスフォーム
	 * @param matrix 乗算する行列
	 * @return 変換後の軸沿いボックス
	 */
	AxisAlignedBox scaledTransform(const Matrix34& matrix) const;

	/**
	 * スケール有りトランスフォーム
	 * @param matrix 乗算する行列
	 * @return 変換後の軸沿いボックス
	 */
	AxisAlignedBox scaledTransform(const Matrix44& matrix) const;

	//--------------------------------------------------------------------------
	// 距離
	//--------------------------------------------------------------------------
	/**
	 * 点距離
	 * @param point 距離判定する点
	 * @return 距離
	 */
	float getDistance(const Vector3& point) const{
		return Math::sqrt(getSquaredDistance(point));
	}

	/**
	 * 点距離の二乗
	 * @param point 距離判定する点
	 * @return 距離の二乗
	 */
	float getSquaredDistance(const Vector3& point) const;

	//--------------------------------------------------------------------------
	/**
	 * 軸沿いボックス距離
	 * @param axisAlignedBox 距離判定する軸沿いボックス
	 * @return 距離
	 */
	float getDistance(const AxisAlignedBox& axisAlignedBox) const{
		return Math::sqrt(getSquaredDistance(axisAlignedBox));
	}

	/**
	 * 軸沿いボックス距離の二乗
	 * @param axisAlignedBox 距離判定する軸沿いボックス
	 * @return 距離の二乗
	 */
	float getSquaredDistance(const AxisAlignedBox& axisAlignedBox) const;

	//--------------------------------------------------------------------------
	/**
	 * カプセル距離
	 * @param capsule 距離判定するカプセル
	 * @return 距離
	 */
	float getDistance(const Capsule& capsule) const{
		return Math::sqrt(getSquaredDistance(capsule));
	}

	/**
	 * カプセル距離の二乗
	 * @param capsule 距離判定するカプセル
	 * @return 距離の二乗
	 */
	float getSquaredDistance(const Capsule& capsule) const;

	//--------------------------------------------------------------------------
	/**
	 * コーン距離
	 * @param cone 距離判定するコーン
	 * @return 距離
	 */
	float getDistance(const Cone& cone) const{
		return Math::sqrt(getSquaredDistance(cone));
	}

	/**
	 * コーン距離の二乗
	 * @param cone 距離判定するコーン
	 * @return 距離の二乗
	 */
	float getSquaredDistance(const Cone& cone) const;

	//--------------------------------------------------------------------------
	/**
	 * ライン距離
	 * @param line 距離判定するライン
	 * @return 距離
	 */
	float getDistance(const Line& line) const{
		return Math::sqrt(getSquaredDistance(line));
	}

	/**
	 * ライン距離の二乗
	 * @param line 距離判定するライン
	 * @return 距離の二乗
	 */
	float getSquaredDistance(const Line& line) const;

	//--------------------------------------------------------------------------
	/**
	 * 指向性ボックス距離
	 * @param orientedBox 距離判定する指向性ボックス
	 * @return 距離
	 */
	float getDistance(const OrientedBox& orientedBox) const{
		return Math::sqrt(getSquaredDistance(orientedBox));
	}

	/**
	 * 指向性ボックス距離の二乗
	 * @param orientedBox 距離判定する指向性ボックス
	 * @return 距離の二乗
	 */
	float getSquaredDistance(const OrientedBox& orientedBox) const;

	//--------------------------------------------------------------------------
	/**
	 * 平面距離
	 * @param plane 距離判定する平面
	 * @return 距離
	 */
	float getDistance(const Plane& plane) const;

	/**
	 * 平面距離の二乗
	 * @param plane 距離判定する平面
	 * @return 距離の二乗
	 */
	float getSquaredDistance(const Plane& plane) const{
		float distance = getDistance(plane);
		return (distance * distance);
	}

	//--------------------------------------------------------------------------
	/**
	 * レイ距離
	 * @param ray 距離判定するレイ
	 * @return 距離
	 */
	float getDistance(const Ray& ray) const{
		return Math::sqrt(getSquaredDistance(ray));
	}

	/**
	 * レイ距離の二乗
	 * @param ray 距離判定するレイ
	 * @return 距離の二乗
	 */
	float getSquaredDistance(const Ray& ray) const;

	//--------------------------------------------------------------------------
	/**
	 * セグメント距離
	 * @param segment 距離判定するセグメント
	 * @return 距離
	 */
	float getDistance(const Segment& segment) const{
		return Math::sqrt(getSquaredDistance(segment));
	}

	/**
	 * セグメント距離の二乗
	 * @param segment 距離判定するセグメント
	 * @return 距離の二乗
	 */
	float getSquaredDistance(const Segment& segment) const;

	//--------------------------------------------------------------------------
	/**
	 * 球距離
	 * @param sphere 距離判定する球
	 * @return 距離
	 */
	float getDistance(const Sphere& sphere) const{
		return Math::sqrt(getSquaredDistance(sphere));
	}

	/**
	 * 球距離の二乗
	 * @param sphere 距離判定する球
	 * @return 距離の二乗
	 */
	float getSquaredDistance(const Sphere& sphere) const;

	//--------------------------------------------------------------------------
	/**
	 * 三角距離
	 * @param triangle 距離判定する三角
	 * @return 距離
	 */
	float getDistance(const Triangle& triangle) const{
		return Math::sqrt(getSquaredDistance(triangle));
	}

	/**
	 * 三角距離の二乗
	 * @param triangle 距離判定する三角
	 * @return 距離の二乗
	 */
	float getSquaredDistance(const Triangle& triangle) const;

	//--------------------------------------------------------------------------
	// 交差
	//--------------------------------------------------------------------------
	/**
	 * 点交差
	 * @param point 交差判定する点
	 * @return 交差していればtrue
	 */
	bool intersect(const Vector3& point) const;

	//--------------------------------------------------------------------------
	/**
	 * 軸沿いボックス交差
	 * @param axisAlignedBox 交差判定する軸沿いボックス
	 * @return 交差していればtrue
	 */
	bool intersect(const AxisAlignedBox& axisAlignedBox) const;

	//--------------------------------------------------------------------------
	/**
	 * カプセル交差
	 * @param capsule 交差判定するカプセル
	 * @return 交差していればtrue
	 */
	bool intersect(const Capsule& capsule) const;

	//--------------------------------------------------------------------------
	/**
	 * コーン交差
	 * @param cone 交差判定するコーン
	 * @return 交差していればtrue
	 */
	bool intersect(const Cone& cone) const;

	//--------------------------------------------------------------------------
	/**
	 * ライン交差
	 * @param line 交差判定するライン
	 * @return 交差していればtrue
	 */
	bool intersect(const Line& line) const;

	//--------------------------------------------------------------------------
	/**
	 * 指向性ボックス交差
	 * @param orientedBox 交差判定する指向性ボックス
	 * @return 交差していればtrue
	 */
	bool intersect(const OrientedBox& orientedBox) const;

	//--------------------------------------------------------------------------
	/**
	 * 平面交差
	 * @param plane 交差判定する平面
	 * @return 交差していればtrue
	 */
	bool intersect(const Plane& plane) const;

	//--------------------------------------------------------------------------
	/**
	 * レイ交差
	 * @param ray 交差判定するレイ
	 * @return 交差していればtrue
	 */
	bool intersect(const Ray& ray) const;

	//--------------------------------------------------------------------------
	/**
	 * セグメント交差
	 * @param segment 交差判定するセグメント
	 * @return 交差していればtrue
	 */
	bool intersect(const Segment& segment) const;

	//--------------------------------------------------------------------------
	/**
	 * 球交差
	 * @param sphere 交差判定する球
	 * @return 交差していればtrue
	 */
	bool intersect(const Sphere& sphere) const;

	//--------------------------------------------------------------------------
	/**
	 * 三角交差
	 * @param triangle 交差判定する三角
	 * @return 交差していればtrue
	 */
	bool intersect(const Triangle& triangle) const;

	//--------------------------------------------------------------------------
	// 論理演算
	//--------------------------------------------------------------------------
	/**
	 * 指向性ボックスが同じかどうか
	 * @param target 比較する指向性ボックス
	 * @return 同じ値であればtrueを返す
	 */
	inline bool operator ==(const OrientedBox& target) const{
		return ((rotationMatrix_ == target.rotationMatrix_) &&
			(center_ == target.center_) && (extent_ == target.extent_));
	}

	/**
	 * 指向性ボックスが同じかどうか
	 * @param target 比較する指向性ボックス
	 * @param epsilon 誤差
	 * @return 誤差の範囲内で同じ値であればtrueを返す
	 */
	inline bool epsilonEquals(
		const OrientedBox& target, float epsilon) const{
		Assert(epsilon >= 0.f);
		return (
			rotationMatrix_.epsilonEquals(target.rotationMatrix_, epsilon) &&
			center_.epsilonEquals(target.center_, epsilon) &&
			extent_.epsilonEquals(target.extent_, epsilon));
	}

	/**
	 * 指向性ボックスが同じでないかどうか
	 * @param target 比較する指向性ボックス
	 * @return 同じでない値であればtrueを返す
	 */
	inline bool operator !=(const OrientedBox& target) const{
		return ((rotationMatrix_ != target.rotationMatrix_) ||
			(center_ != target.center_) || (extent_ != target.extent_));
	}

	/**
	 * 指向性ボックスが同じでないかどうか
	 * @param target 比較する指向性ボックス
	 * @param epsilon 誤差
	 * @return 誤差の範囲内で同じでない値であればtrueを返す
	 */
	inline bool notEpsilonEquals(
		const OrientedBox& target, float epsilon) const{
		Assert(epsilon >= 0.f);
		return (
			rotationMatrix_.notEpsilonEquals(target.rotationMatrix_, epsilon) ||
			center_.notEpsilonEquals(target.center_, epsilon) ||
			extent_.notEpsilonEquals(target.extent_, epsilon));
	}

	//--------------------------------------------------------------------------
	// その他
	//--------------------------------------------------------------------------
	/**
	 * 文字列化
	 * @return 指向性ボックスの文字列表記
	 */
	inline String toString() const{
		String returnString;
		returnString.format("{ { ( %.8f, %.8f, %.8f ) "
			"( %.8f, %.8f, %.8f ) ( %.8f, %.8f, %.8f ) } "
			"( %.8f, %.8f, %.8f ) ( %.8f, %.8f, %.8f ) }",
			rotationMatrix_.m00, rotationMatrix_.m01, rotationMatrix_.m02,
			rotationMatrix_.m10, rotationMatrix_.m11, rotationMatrix_.m12,
			rotationMatrix_.m20, rotationMatrix_.m21, rotationMatrix_.m22,
			center_.x, center_.y, center_.z, extent_.x, extent_.y, extent_.z);
		return returnString;
	}

private:
	//--------------------------------------------------------------------------
	// メンバ変数
	//--------------------------------------------------------------------------
	// 回転行列
	Matrix33 rotationMatrix_;
	// 中心
	Vector3 center_;
	// 大きさ
	Vector3 extent_;

};

//------------------------------------------------------------------------------
} // End of namespace Lamp
#endif // End of ORIENTED_BOX_H_
//------------------------------------------------------------------------------
