import { assert } from "../../../assert.js";
import { plane3_normalize } from "../plane/plane3_normalize.js";

/**
 *
 * Set frustum from projection matrix
 * NOTE: uses Gribb/Hartmann method
 * @see "Fast Extraction of Viewing Frustum Planes from the WorldView-Projection Matrix", 2001 by Gribb & Hartmann
 * @param {number[]|Float32Array} frustum_planes tuples of 4, where each tuple is a plane normal (x,y,z) followed by a planar offset constant [normal_x, normal_y, normal_z, constant]
 * @param {number[]} m4 assumed to be view-projection matrix
 */
export function frustum_from_projection_matrix_array(frustum_planes, m4) {
    assert.isArrayLike(frustum_planes, 'frustum_planes');
    assert.greaterThanOrEqual(frustum_planes.length, 24, 'frustum_planes.length');

    assert.isArrayLike(m4, 'm4');
    assert.greaterThanOrEqual(m4.length, 16, 'm4.length');

    const me0 = m4[0];
    const me3 = m4[3];

    const me4 = m4[4];
    const me7 = m4[7];

    const me8 = m4[8];
    const me11 = m4[11];

    const me12 = m4[12];
    const me15 = m4[15];

    plane3_normalize(frustum_planes, 0, me3 - me0, me7 - me4, me11 - me8, me15 - me12);
    plane3_normalize(frustum_planes, 4, me3 + me0, me7 + me4, me11 + me8, me15 + me12);

    const me1 = m4[1];
    const me5 = m4[5];
    const me9 = m4[9];
    const me13 = m4[13];

    plane3_normalize(frustum_planes, 8, me3 + me1, me7 + me5, me11 + me9, me15 + me13);
    plane3_normalize(frustum_planes, 12, me3 - me1, me7 - me5, me11 - me9, me15 - me13);

    const me2 = m4[2];
    const me6 = m4[6];
    const me10 = m4[10];
    const me14 = m4[14];

    plane3_normalize(frustum_planes, 16, me3 - me2, me7 - me6, me11 - me10, me15 - me14);
    plane3_normalize(frustum_planes, 20, me3 + me2, me7 + me6, me11 + me10, me15 + me14);
}
