import { sign_not_zero } from "../../../../math/sign_not_zero.js";
import { v3_length } from "../../../vec3/v3_length.js";

/**
 * @see A Survey of Efficient Representations for Independent Unit Vectors (Journal of Computer Graphics Techniques Vol. 3, No. 2, 2014) - page 13
 * @see https://gamedev.stackexchange.com/questions/169508/octahedral-impostors-octahedral-mapping
 * @param {number[]|Vector3|Float32Array} output
 * @param {number} output_offset
 * @param {number} u range [-1,1]
 * @param {number} v range [-1,1]
 * @returns {number} length of octahedral vector, larger value means more distortion
 */
export function decode_octahedron_to_unit(
    output, output_offset,
    u, v
) {
    let v_x = u;
    let v_z = v;

    const abs_x = Math.abs(v_x);
    const abs_z = Math.abs(v_z);

    let v_y = 1 - abs_x - abs_z;

    // Handle octahedron's fold
    if (v_y < 0) {
        v_x = (1 - abs_z) * sign_not_zero(v_x);
        v_z = (1 - abs_x) * sign_not_zero(v_z);
    }

    // normalize
    const octahedral_length = v3_length(v_x, v_y, v_z);

    const m = 1 / octahedral_length;

    output[output_offset] = v_x * m;
    output[output_offset + 1] = v_y * m;
    output[output_offset + 2] = v_z * m;

    return octahedral_length;
}
