import { v2_length } from "../../../vec2/v2_length.js";
import { v3_dot } from "../../../vec3/v3_dot.js";

/*
@source https://aras-p.info/texts/CompactNormalStorage.html#method04spheremap
@source Siggraph 99
@source Cry Engine 3, presented by Martin Mittring in "A bit more Deferred"

half2 encode (half3 n, float3 view)
{
    half2 enc = normalize(n.xy) * (sqrt(-n.z*0.5+0.5));
    enc = enc*0.5+0.5;
    return enc;
}
half3 decode (half4 enc, float3 view)
{
    half4 nn = enc*half4(2,2,0,0) + half4(-1,-1,1,-1);
    half l = dot(nn.xyz,-nn.xyw);
    nn.z = l;
    nn.xy *= sqrt(l);
    return nn.xyz * 2 + half3(0,0,-1);
}
 */


/**
 * Encode v3 to v2
 * @param {number[]} output
 * @param {number} output_offset
 * @param {number} x
 * @param {number} y
 * @param {number} z
 */
export function encode_unit_to_spheremap(output, output_offset, x, y, z) {
    const length_xy = v2_length(x, y);

    const norm_xy_x = x / length_xy;
    const norm_xy_y = y / length_xy;

    const z_factor = Math.sqrt(-z * 0.5 - 0.5) * 0.5;

    const enc_x = norm_xy_x * z_factor + 0.5;
    const enc_y = norm_xy_y * z_factor + 0.5;

    output[output_offset] = enc_x;
    output[output_offset + 1] = enc_y;
}

/**
 * @param {number[]} output
 * @param {number} output_offset
 * @param {number} x range [-1,1]
 * @param {number} y range [-1,1]
 */
function decode_spheremap_to_unit(output, output_offset, x, y) {
    const nn4_x = x * 2 - 1;
    const nn4_y = y * 2 - 1;
    const nn4_z = 1;
    const nn4_w = -1;

    const l = v3_dot(nn4_x, nn4_y, nn4_z, -nn4_x, -nn4_y, -nn4_w);

    const nn_z = l;

    const l_sqrt = Math.sqrt(l);

    const nn_x = nn4_x * l_sqrt;
    const nn_y = nn4_y * l_sqrt;

    const _x = nn_x * 2;
    const _y = nn_y * 2;
    const _z = nn_z * 2 - 1;

    output[output_offset] = _x;
    output[output_offset + 1] = _y;
    output[output_offset + 2] = _z;
}
