import { SH3_COEFFICIENTS } from "./SH3_COEFFICIENTS.js";

/**
 * Sample value from a 3-band spherical harmonic defined by 9 coefficients
 *
 * @see https://github.com/mrdoob/three.js/blob/d081c5a3501d272d19375fab1b01fedf9df29b22/src/math/SphericalHarmonics3.js#L55
 * @see https://graphics.stanford.edu/papers/envmap/envmap.pdf
 * @see https://www.ppsloan.org/publications/StupidSH36.pdf
 * @param {number[]} result Result will be written here
 * @param {number} result_offset
 * @param {number[]} harmonics coefficients are read from here
 * @param {number} harmonics_offset offset into coefficients array where to start reading the data
 * @param {number} dimension_count number of encoded dimensions, this is essentially a shortcut for multiple harmonics being read at the same time, such as with RGB values
 * @param {number[]} direction 3d vector read from here, we will read 3 values from here to sample spherical harmonic, direction is assumed to be normalized
 * @param {number} direction_offset offset into direction array
 */
export function sh3_sample_by_direction(
    result, result_offset,
    harmonics, harmonics_offset,
    dimension_count,
    direction, direction_offset
) {
    const x = direction[direction_offset];
    const y = direction[direction_offset + 1];
    const z = direction[direction_offset + 2];

    let channel_value;

    for (let i = 0; i < dimension_count; i++) {
        const offset = harmonics_offset + dimension_count * i;

        // band 0
        channel_value = harmonics[offset] * SH3_COEFFICIENTS[0];

        // band 1
        channel_value += harmonics[offset + 1] * SH3_COEFFICIENTS[1] * y;
        channel_value += harmonics[offset + 2] * SH3_COEFFICIENTS[2] * z;
        channel_value += harmonics[offset + 3] * SH3_COEFFICIENTS[3] * x;

        // band 2
        channel_value += harmonics[offset + 4] * SH3_COEFFICIENTS[4] * (x * y);
        channel_value += harmonics[offset + 5] * SH3_COEFFICIENTS[5] * (y * z);
        channel_value += harmonics[offset + 6] * SH3_COEFFICIENTS[6] * (3.0 * z * z - 1.0);
        channel_value += harmonics[offset + 7] * SH3_COEFFICIENTS[7] * (x * z);
        channel_value += harmonics[offset + 8] * SH3_COEFFICIENTS[8] * (x * x - y * y);

        // write out
        result[result_offset + i] = channel_value;
    }
}
