/**
 * TODO compute slices to minimize world-space volume difference between clusters
 * @param {number[]} input_frustum_corners corners of input frustum
 * @param {number} tr_x slices in X axis
 * @param {number} tr_y slices in Y axis
 * @param {number} tr_z slices in Z axis
 * @param {number[]} output_frustum_corners
 */
export function slice_frustum_linear_to_points(
    input_frustum_corners,
    tr_x, tr_y, tr_z,
    output_frustum_corners
) {
    // read out view frustum scratch_corners
    const x_000 = input_frustum_corners[0];
    const y_000 = input_frustum_corners[1];
    const z_000 = input_frustum_corners[2];

    const x_001 = input_frustum_corners[3];
    const y_001 = input_frustum_corners[4];
    const z_001 = input_frustum_corners[5];

    const x_010 = input_frustum_corners[6];
    const y_010 = input_frustum_corners[7];
    const z_010 = input_frustum_corners[8];

    const x_011 = input_frustum_corners[9];
    const y_011 = input_frustum_corners[10];
    const z_011 = input_frustum_corners[11];

    const x_100 = input_frustum_corners[12];
    const y_100 = input_frustum_corners[13];
    const z_100 = input_frustum_corners[14];

    const x_101 = input_frustum_corners[15];
    const y_101 = input_frustum_corners[16];
    const z_101 = input_frustum_corners[17];

    const x_110 = input_frustum_corners[18];
    const y_110 = input_frustum_corners[19];
    const z_110 = input_frustum_corners[20];

    const x_111 = input_frustum_corners[21];
    const y_111 = input_frustum_corners[22];
    const z_111 = input_frustum_corners[23];


    const x_plane_count = tr_x + 1;
    const y_plane_count = tr_y + 1;
    const z_plane_count = tr_z + 1;

    const z_slice_stride = x_plane_count * y_plane_count;

    for (let i_z = 0; i_z < z_plane_count; i_z++) {
        const r_0 = i_z / tr_z;
        const r_1 = 1 - r_0;

        const z_offset = i_z * z_slice_stride;

        for (let i_y = 0; i_y < y_plane_count; i_y++) {

            const v_0 = i_y / tr_y;
            const v_1 = 1 - v_0;

            const y_offset = z_offset + i_y * x_plane_count;

            for (let i_x = 0; i_x < x_plane_count; i_x++) {
                const u_0 = i_x / tr_x;
                const u_1 = 1 - u_0;

                const m_000 = u_1 * v_1 * r_1;
                const m_001 = u_1 * v_1 * r_0;
                const m_010 = u_1 * v_0 * r_1;
                const m_011 = u_1 * v_0 * r_0;
                const m_100 = u_0 * v_1 * r_1;
                const m_101 = u_0 * v_1 * r_0;
                const m_110 = u_0 * v_0 * r_1;
                const m_111 = u_0 * v_0 * r_0;

                // interpolate view frustum scratch_corners
                const x = x_000 * m_000 + x_001 * m_001 + x_010 * m_010 + x_011 * m_011 + x_100 * m_100 + x_101 * m_101 + x_110 * m_110 + x_111 * m_111;
                const y = y_000 * m_000 + y_001 * m_001 + y_010 * m_010 + y_011 * m_011 + y_100 * m_100 + y_101 * m_101 + y_110 * m_110 + y_111 * m_111;
                const z = z_000 * m_000 + z_001 * m_001 + z_010 * m_010 + z_011 * m_011 + z_100 * m_100 + z_101 * m_101 + z_110 * m_110 + z_111 * m_111;

                // write out cluster corner position
                const index = y_offset + i_x
                const address = index * 3;

                output_frustum_corners[address] = x;
                output_frustum_corners[address + 1] = y;
                output_frustum_corners[address + 2] = z;
            }

        }
    }
}
