Source: math/Frustum.js

import { Plane } from './Plane.js';
import { Vector3 } from './Vector3.js';

var _vec3_1 = new Vector3();

/**
 * @constructor
 * @memberof zen3d
 * @param {zen3d.Plane} p0
 * @param {zen3d.Plane} p1
 * @param {zen3d.Plane} p2
 * @param {zen3d.Plane} p3
 * @param {zen3d.Plane} p4
 * @param {zen3d.Plane} p5
 */
function Frustum(p0, p1, p2, p3, p4, p5) {
	this.planes = [
		(p0 !== undefined) ? p0 : new Plane(),
		(p1 !== undefined) ? p1 : new Plane(),
		(p2 !== undefined) ? p2 : new Plane(),
		(p3 !== undefined) ? p3 : new Plane(),
		(p4 !== undefined) ? p4 : new Plane(),
		(p5 !== undefined) ? p5 : new Plane()
	];
}

Object.assign(Frustum.prototype, /** @lends zen3d.Frustum.prototype */{

	set: function(p0, p1, p2, p3, p4, p5) {
		var planes = this.planes;

		planes[0].copy(p0);
		planes[1].copy(p1);
		planes[2].copy(p2);
		planes[3].copy(p3);
		planes[4].copy(p4);
		planes[5].copy(p5);

		return this;
	},

	setFromMatrix: function(m) {
		var planes = this.planes;
		var me = m.elements;
		var me0 = me[0],
			me1 = me[1],
			me2 = me[2],
			me3 = me[3];
		var me4 = me[4],
			me5 = me[5],
			me6 = me[6],
			me7 = me[7];
		var me8 = me[8],
			me9 = me[9],
			me10 = me[10],
			me11 = me[11];
		var me12 = me[12],
			me13 = me[13],
			me14 = me[14],
			me15 = me[15];

		planes[0].setComponents(me3 - me0, me7 - me4, me11 - me8, me15 - me12).normalize();
		planes[1].setComponents(me3 + me0, me7 + me4, me11 + me8, me15 + me12).normalize();
		planes[2].setComponents(me3 + me1, me7 + me5, me11 + me9, me15 + me13).normalize();
		planes[3].setComponents(me3 - me1, me7 - me5, me11 - me9, me15 - me13).normalize();
		planes[4].setComponents(me3 - me2, me7 - me6, me11 - me10, me15 - me14).normalize();
		planes[5].setComponents(me3 + me2, me7 + me6, me11 + me10, me15 + me14).normalize();

		return this;
	},

	intersectsSphere: function(sphere) {
		var planes = this.planes;
		var center = sphere.center;
		var negRadius = -sphere.radius;

		for (var i = 0; i < 6; i++) {
			var distance = planes[i].distanceToPoint(center);

			if (distance < negRadius) {
				return false;
			}
		}

		return true;
	},

	intersectsBox: function(box) {
		var planes = this.planes;

		for (var i = 0; i < 6; i++) {
			var plane = planes[i];

			// corner at max distance

			_vec3_1.x = plane.normal.x > 0 ? box.max.x : box.min.x;
			_vec3_1.y = plane.normal.y > 0 ? box.max.y : box.min.y;
			_vec3_1.z = plane.normal.z > 0 ? box.max.z : box.min.z;

			// if both outside plane, no intersection

			if (plane.distanceToPoint(_vec3_1) < 0) {
				return false;
			}
		}

		return true;
	},

	clone: function () {
		return new this.constructor().copy(this);
	},

	copy: function (frustum) {
		var planes = this.planes;

		for (var i = 0; i < 6; i++) {
			planes[i].copy(frustum.planes[i]);
		}

		return this;
	}

});

export { Frustum };