//===========================================================================//
// File:	extntbox.hh                                                        //
// Project: MUNGA           Brick: Math Library                              //
// Contents: Interface specification of bounding box class                   //
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               //
// --------  ---  ---------------------------------------------------------- //
// 01/07/95  JMA  Initial coding.                                            //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995 Virtual World Entertainment, Inc.                 //
// All Rights reserved worldwide                                             //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL               //
//===========================================================================//

#pragma once

#include "Stuff.hpp"
#include "Scalar.hpp"
#include "MArray.hpp"
#include "Plane.hpp"

namespace Stuff {class ExtentBox;}

#if !defined(Spew)
	void
		Spew(
			const char* group,
			const Stuff::ExtentBox& box
		);
#endif

namespace Stuff {

	class Vector3D;
	class Point3D;
	class NotationFile;
	class OBB;

	//~~~~~~~~~~~~~~~~~~~~~~~~~ ExtentBox ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

	class ExtentBox
	{
	 public:
		Scalar
			minX,
			maxX,
			minY,
			maxY,
			minZ,
			maxZ;

		ExtentBox() {}
		ExtentBox(
			const Vector3D &min,
			const Vector3D &max
		);
		ExtentBox(const ExtentBox &box);
		explicit ExtentBox(const OBB& obb);

		const Scalar&
			operator[](int index) const
				{Check_Object(this); return (&minX)[index];}
		Scalar&
			operator[](int index)
				{Check_Object(this); return (&minX)[index];}

		void
			ComputeBounds(ReadOnlyArrayOf<Point3D> &points);
		Scalar
			GetVolume() const
				{Check_Object(this); return (maxX-minX)*(maxY-minY)*(maxZ-minZ);}

		ExtentBox&
			Intersect(
				const ExtentBox &box_1,
				const ExtentBox &box_2
			);
		ExtentBox&
			Union(
				const ExtentBox &box_1,
				const ExtentBox &box_2
			);
		ExtentBox&
			Union(
				const ExtentBox &box_1,
				const Vector3D &point
			);
		Vector3D*
			Constrain(Vector3D *point) const;

		bool
			Contains(const Vector3D &point) const;
		bool
			Contains(const ExtentBox &box) const;
		bool
			Intersects(const ExtentBox &box) const;

		void
			GetCenterpoint(Point3D *point) const;

		void
			TestInstance() const;
		static bool
			TestClass();
		#if !defined(Spew)
			friend void
				::Spew(
					const char* group,
					const ExtentBox& box
				);
		#endif
	};

	//~~~~~~~~~~~~~~~~~~~~~~~~~ ExtentBox functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

	void
		Use_Scalar_In_Sorted_Array(
			DynamicArrayOf<Scalar> *values,
			Scalar value,
			unsigned *max_index,
			unsigned block_size,
			Scalar threshold = SMALL
		);

	void
		Find_Planes_Of_Boxes(
			DynamicArrayOf<Plane> *planes,
			const DynamicArrayOf<ExtentBox> &boxes
		);

}

namespace MemoryStreamIO {

	inline Stuff::MemoryStream&
		Read(
			Stuff::MemoryStream* stream,
			Stuff::ExtentBox *output
		)
			{return stream->ReadBytes(output, sizeof(*output));}
	inline Stuff::MemoryStream&
		Write(
			Stuff::MemoryStream* stream,
			const Stuff::ExtentBox *input
		)
			{return stream->WriteBytes(input, sizeof(*input));}

}
