/*
/ BOUNDS.H
/ ********
/ Bounding volume definition and
/ implementation, currently only
/ for box volumes.
/
/ Will Beddow 2010 - http://343gs.com/brainstem
/
/ This software is currently under development
/ and is subject to change and improvement. Some
/ aspects of the system are incomplete and/or 
/ unstable due to ongoing implementation.
/
*/

#ifndef __BOUNDS_H__
#define __BOUNDS_H__

#include "Compile.h"
#include "Types.h"
#include "Matrix.h"

namespace Brainstem
{

class BoundingVolume
	{
	public:
		BoundingVolume()
		{
			Max = Vector3<float>(-10000.0f, -10000.0f, -10000.0f);
			Min = Vector3<float>(10000.0f, 10000.0f, 10000.0f);
		}
		BoundingVolume(Vector3<float> max, Vector3<float> min)
		{
			Max = max;
			Min = min;
		}

		~BoundingVolume() { }

		void Set(Vector3<float> position)
		{
			if(position.X < Min.X) 
				Min.X = position.X;

			if(position.X > Max.X) 
				Max.X = position.X;

			if(position.Y < Min.Y) 
				Min.Y = position.Y;

			if(position.Y > Max.Y) 
				Max.Y = position.Y;

			if(position.Z < Min.Z) 
				Min.Z = position.Z;

			if(position.Z > Max.Z) 
				Max.Z = position.Z;
		}

		void ApplyTransforms(Matrix4<float> matrix)
		{
			matrix.TransformVector(Min);
			matrix.TransformVector(Max);
		}

		Vector3<float>* GetCorners()
		{
			Vector3<float> corners[] = { Min, 
				Vector3<float>(Min.X, Min.Y, Max.Z), 
				Vector3<float>(Min.X, Max.Y, Max.Z),
				Vector3<float>(Min.X, Max.Y, Min.Z),
				Vector3<float>(Max.X, Min.Y, Min.Z),
				Vector3<float>(Max.X, Min.Y, Max.Z),
				Max,
				Vector3<float>(Min.X, Max.Y, Max.Z) };

			return corners;
		}

		bool Intersects(BoundingVolume* target)
		{
			Vector3<float>* targetCorners = target->GetCorners();

			for (int i = 0; i < 8; i++)
				if (Intersects(targetCorners[i]))
					return true;

			return false;
		}

		bool Intersects(Vector3<float> position)
		{
			if (position.X < Min.X || position.Y < Min.Y || position.Z > Min.Z)
				return false;

			if (position.X > Max.X || position.Y > Max.Y || position.Z < Max.Z)
				return false;

			return true;
		}

		bool IntersectsXZ(Vector3<float> position)
		{
			if (position.X < Min.X || position.Z > Min.Z)
				return false;

			if (position.X > Max.X || position.Z < Max.Z)
				return false;

			return true;
		}

		Vector3<float> GetCenter() { return (Max - Min) / 2.0f; }

		Vector3<float> Min, Max;
	};
}

#endif
