#include "bvolumes.h"

using namespace std;

namespace VRUT
{

	const unsigned int AABB::FaceQuadIndices[24] = {
		3, 1, 5, 7,			// Front face		- FRUSTUM_NEAR
		6, 4, 0, 2,			// Back face		- FRUSTUM_FAR
		2, 0, 1, 3,			// Left face		- FRUSTUM_LEFT
		7, 5, 4, 6,			// Right face		- FRUSTUM_RIGHT
		2, 3, 7, 6,			// Top face			- FRUSTUM_TOP
		1, 0, 4, 5,			// Bottom face		- FRUSTUM_BOTTOM
	};

	const AABB AABB::DefaultClipVolume = AABB(Vector3(-1.0f, -1.0f, -1.0f), Vector3(1.0f, 1.0f, 1.0f));

	AABB AABB::TransformAndClipHomogeneous(const Matrix &mvp, const vector<Vector4> &clip_planes) const
	{
		AABB result;		// Default is invalid AABB

		// Transform input AABB
		Vector4 transformed_aabb_vertices[8];
		for (int i = 0; i < 8; i++)		transformed_aabb_vertices[i] = mvp.TransformCoord(Vector4(GetVertex(i), 1.0f));

		vector<Vector4> face_vertices;		face_vertices.reserve(4 + clip_planes.size());		// Each clip plane adds zero or one point
		vector<Vector4> tmp;				tmp.reserve(4 + clip_planes.size());				// Each clip plane adds zero or one point

		for (int face = 0; face < 6; face++)
		{
			// Get face vertices
			face_vertices.resize(4);
			for (int v = 0; v < 4; v++)
				face_vertices[v] = transformed_aabb_vertices[AABB::FaceQuadIndices[face*4+v]];

			// Clip the quad with each clip plane. Use Sutherland-Hodgman algorithm
			Vector4::PlaneClipPolygonHomogeneous(face_vertices, tmp, clip_planes);

			// Divide all coordinates by w, and add the clipped quad into the output AABB
			for (size_t v = 0; v < face_vertices.size(); v++)
				result.ExpandWithPoint(Vector3(face_vertices[v]) / face_vertices[v].w);
		}

		return result;
	}

}
