//------------------------------------------------------------------------------
// 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 "Test/stdafx.h"
#include "Geometry/Primitive/RayTest.h"
#include "Geometry/Primitive/Ray.h"

//------------------------------------------------------------------------------
// コンストラクタ
RayTest::RayTest(String name) : TestCase(name){
}
//------------------------------------------------------------------------------
// テストスィートの取得
Test* RayTest::suite(){
	TestSuite* suite = new TestSuite("RayTest");
	suite->addTest(new TestCaller(RayTest, testConstructor));
	suite->addTest(new TestCaller(RayTest, testFixedNumber));
	suite->addTest(new TestCaller(RayTest, testSetValue));
	suite->addTest(new TestCaller(RayTest, testGetValue));
	suite->addTest(new TestCaller(RayTest, testRayArithmetic));
	suite->addTest(new TestCaller(RayTest, testTransform));
	suite->addTest(new TestCaller(RayTest, testLogicalOperation));
	suite->addTest(new TestCaller(RayTest, testToString));
	return suite;
}
//------------------------------------------------------------------------------
// コンストラクタテスト
void RayTest::testConstructor(){
	TestEquals(24, (int)sizeof(Ray));
	Ray ray0(-1.f, -2.f, -3.f, 1.f, 2.f, 3.f);
	Ray ray1(Vector3(-1.f, -2.f, -3.f), Vector3(1.f, 2.f, 3.f));
	TestAssert(ray0 == ray1);
	Ray ray2(ray1);
	TestAssert(ray0 == ray2);
	ray1 = ray2;
	TestAssert(ray0 == ray1);
	Ray ray3(Ray::zero);
	TestAssert(ray3 == Ray(0.f, 0.f, 0.f, 0.f, 0.f, 0.f));
	float array[] = { -1.f, -2.f, -3.f, 1.f, 2.f, 3.f };
	Ray ray4(array);
	TestAssert(ray0 == ray4);
}
//------------------------------------------------------------------------------
// 定数テスト
void RayTest::testFixedNumber(){
	Ray ray0(0.f, 0.f, 0.f, 0.f, 0.f, 0.f);
	TestAssert(ray0 == Ray::zero);
}
//------------------------------------------------------------------------------
// 値の設定テスト
void RayTest::testSetValue(){
	Ray ray0(-1.f, -2.f, -3.f, 1.f, 2.f, 3.f);
	Ray ray1;
	ray1.set(-1.f, -2.f, -3.f, 1.f, 2.f, 3.f);
	TestAssert(ray0 == ray1);
	ray1.set(Vector3(-1.f, -2.f, -3.f), Vector3(1.f, 2.f, 3.f));
	TestAssert(ray0 == ray1);
	float array[] = { -1.f, -2.f, -3.f, 1.f, 2.f, 3.f };
	ray1.set(array);
}
//------------------------------------------------------------------------------
// 値の取得テスト
void RayTest::testGetValue(){
	Ray ray0(-1.f, -2.f, -3.f, 1.f, 2.f, 3.f);
	TestAssert(ray0.getOrigin() == Vector3(-1.f, -2.f, -3.f));
	TestAssert(ray0.getDirection() == Vector3(1.f, 2.f, 3.f));
}
//------------------------------------------------------------------------------
// レイ演算
void RayTest::testRayArithmetic(){
	TestAssert(Ray(0.f, 0.f, 0.f, 0.f, 0.f, 0.f).isZero());
	TestAssert(Ray(1.f, 2.f, 3.f, 0.f, 0.f, 0.f).isZero());
}
//------------------------------------------------------------------------------
// 変換テスト
void RayTest::testTransform(){
	Ray ray0(1.f, 2.f, 3.f, 1.f, 2.f, 3.f);
	Ray ray1(Ray::zero);

	Matrix33 mtx33;
	mtx33.setScale(Vector3(1.f, 2.f, 1.f));
	mtx33.addRotationXYZ(Vector3(Math::halfPI, Math::halfPI, Math::halfPI));
	ray1 = ray0.transform(mtx33);
	TestAssert(ray1.epsilonEquals(
		Ray(3.f, 4.f, -1.f, 3.f, 4.f, -1.f), Math::epsilon));

	Matrix34 mtx43;
	mtx43.setScale(Vector3(1.f, 2.f, 1.f));
	mtx43.addRotationXYZ(Vector3(Math::halfPI, Math::halfPI, Math::halfPI));
	mtx43.addTranslation(1.f, 1.f, 1.f);
	ray1 = ray0.transform(mtx43);
	TestAssert(ray1.epsilonEquals(
		Ray(4.f, 5.f, 0.f, 3.f, 4.f, -1.f), Math::epsilon));

	Matrix44 mtx44;
	mtx44.setScale(Vector3(1.f, 2.f, 1.f));
	mtx44.addRotationXYZ(Vector3(Math::halfPI, Math::halfPI, Math::halfPI));
	mtx44.addTranslation(1.f, -1.f, 1.f);
	ray1 = ray0.transform(mtx44);
	TestAssert(ray1.epsilonEquals(
		Ray(4.f, 3.f, 0.f, 3.f, 4.f, -1.f), Math::epsilon));
}
//------------------------------------------------------------------------------
// 論理演算テスト
void RayTest::testLogicalOperation(){
	Ray ray0(0.f, 0.f, 0.f, 1.f, 1.f, 1.f),
		ray1(1.f, 1.f, 1.f, 2.f, 2.f, 2.f),
		ray2(0.f, 0.f, 0.f, 1.f, 1.f, 1.f);
	TestAssert(!(ray0 == ray1));
	TestAssert(ray0 == ray2);
	TestAssert(ray0 != ray1);
	TestAssert(!(ray0 != ray2));
	TestAssert(ray0.epsilonEquals(ray1, 1.f));
	TestAssert(ray0 != ray1);
	TestAssert(ray0.notEpsilonEquals(ray1, 0.5f));
	TestAssert(!ray0.notEpsilonEquals(ray1, 1.f));
	TestAssert(!ray0.notEpsilonEquals(ray2, 0.f));
}
//------------------------------------------------------------------------------
// 文字列テスト
void RayTest::testToString(){
	Ray ray0(12345678.f, 1234.5678f, 0.12345678f,
		12345678.f, 1234.5678f, 0.12345678f);
	TestEquals("{ ( 12345678.00000000, 1234.56774902, 0.12345678 ) "
		"( 12345678.00000000, 1234.56774902, 0.12345678 ) }",
		ray0.toString());
}
//------------------------------------------------------------------------------
