"use strict";
//////////////////////////////////////////////////////////////////////////
//
//  Copyright (C) 2007-2023 zSpace, Inc.  All Rights Reserved.
//
//////////////////////////////////////////////////////////////////////////
Object.defineProperty(exports, "__esModule", { value: true });
exports.DisplaySizeExtractor = void 0;
class DisplaySizeExtractor {
    constructor(xrSession) {
        this._planes = [];
        this._displaySize = { width: 0, height: 0 };
        this._session = xrSession;
        this._referenceSpace = null;
        this._headPos = [0, 0, 0, 1];
        this._raycastLeft = null;
        this._raycastRight = null;
        this._raycastTop = null;
        this._raycastBottom = null;
        this.resolve = null;
        this.reject = null;
    }
    QueryDisplaySize() {
        return new Promise((resolve, reject) => {
            this.resolve = resolve;
            this.reject = reject;
            if (this._referenceSpace === null) {
                this._session
                    .requestReferenceSpace("local")
                    .then((refSpace) => {
                    this._referenceSpace = refSpace;
                    this._session.requestAnimationFrame(this._onXrFrame.bind(this));
                })
                    .catch((err) => {
                    if (this.reject)
                        this.reject(err);
                });
            }
            else {
                this._session.requestAnimationFrame(this._onXrFrame.bind(this));
            }
        });
    }
    _onXrFrame(time, frame) {
        if (!this._referenceSpace || !this.resolve)
            return;
        const view = frame.getViewerPose(this._referenceSpace)?.views[0];
        if (!view)
            return;
        const projection = this._mat4Transpose(view.projectionMatrix);
        const viewInverse = this._mat4Transpose(view.transform.inverse.matrix);
        const combo = this._mat4multiply(projection, viewInverse);
        this._planes = this._extractPlanes(combo);
        this._planes = this._normalizeFrustumPlanes(this._planes);
        this._headPos = [
            view.transform.inverse.position.x,
            view.transform.inverse.position.y,
            view.transform.inverse.position.z,
            view.transform.inverse.position.w,
        ];
        this._raycastLeft = this._intersectRayPlaneDistance(this._headPos, this._planes[0], [0, 0, 0], [1, 0, 0]);
        this._raycastRight = this._intersectRayPlaneDistance(this._headPos, this._planes[1], [0, 0, 0], [-1, 0, 0]);
        this._raycastTop = this._intersectRayPlaneDistance(this._headPos, this._planes[2], [0, 0, 0], [0, 1, 0]);
        this._raycastBottom = this._intersectRayPlaneDistance(this._headPos, this._planes[3], [0, 0, 0], [0, -1, 0]);
        this._displaySize = {
            width: this._raycastLeft + this._raycastRight,
            height: this._raycastTop + this._raycastBottom,
        };
        this.resolve(this._displaySize);
    }
    _intersectRayPlaneDistance(plane_pos, plane_norm, ray_pos, ray_norm) {
        if (plane_pos.length === 4) {
            plane_pos = this._vec4tovec3(plane_pos);
        }
        if (plane_norm.length === 4) {
            plane_norm = this._vec4tovec3(plane_norm);
        }
        return (this._vec3dot(plane_norm, this._vec3subtract(ray_pos, plane_pos)) /
            this._vec3dot(plane_norm, this._vec3subtract([0, 0, 0], ray_norm)));
    }
    _vec3subtract(a, b) {
        const out = [];
        out[0] = a[0] - b[0];
        out[1] = a[1] - b[1];
        out[2] = a[2] - b[2];
        out.length = 3;
        return out;
    }
    _vec3multiply(a, b) {
        const out = [];
        out[0] = a[0] * b[0];
        out[1] = a[1] * b[1];
        out[2] = a[2] * b[2];
        out.length = 3;
        return out;
    }
    _vec3dot(a, b) {
        const x = a[0] * b[0];
        const y = a[1] * b[1];
        const z = a[2] * b[2];
        return x + y + z;
    }
    _mat4Transpose(a) {
        const out = [];
        out[0] = a[0];
        out[1] = a[4];
        out[2] = a[8];
        out[3] = a[12];
        out[4] = a[1];
        out[5] = a[5];
        out[6] = a[9];
        out[7] = a[13];
        out[8] = a[2];
        out[9] = a[6];
        out[10] = a[10];
        out[11] = a[14];
        out[12] = a[3];
        out[13] = a[7];
        out[14] = a[11];
        out[15] = a[15];
        return out;
    }
    _extractPlanes(M, zNear, zFar) {
        return [
            // Left
            [M[12] + M[0], M[13] + M[1], M[14] + M[2], M[15] + M[3]],
            // Right
            [M[12] - M[0], M[13] - M[1], M[14] - M[2], M[15] - M[3]],
            // Top
            [M[12] + M[4], M[13] + M[5], M[14] + M[6], M[15] + M[7]],
            // Bottom
            [M[12] - M[4], M[13] - M[5], M[14] - M[6], M[15] - M[7]],
        ];
    }
    _normalizePlane(plane) {
        const mag = Math.sqrt(plane[0] * plane[0] + plane[1] * plane[1] + plane[2] * plane[2]);
        const normalizedPlane = [];
        normalizedPlane[0] = plane[0] / mag;
        normalizedPlane[1] = plane[1] / mag;
        normalizedPlane[2] = plane[2] / mag;
        normalizedPlane[3] = 1 / mag;
        normalizedPlane.length = 4;
        return normalizedPlane;
    }
    _normalizeFrustumPlanes(planes) {
        return planes.map((plane) => this._normalizePlane(plane));
    }
    _vec4tovec3(v) {
        const out = [];
        out[0] = v[0] * (1 / v[3]);
        out[1] = v[1] * (1 / v[3]);
        out[2] = v[2] * (1 / v[3]);
        out.length = 3;
        return out;
    }
    _vec4TransformMat4(a, m) {
        const out = [0, 0, 0, 1];
        const x = a[0];
        const y = a[1];
        const z = a[2];
        const w = a[3];
        out[0] = m[0] * x + m[4] * y + m[8] * z + m[12] * w;
        out[1] = m[1] * x + m[5] * y + m[9] * z + m[13] * w;
        out[2] = m[2] * x + m[6] * y + m[10] * z + m[14] * w;
        out[3] = m[3] * x + m[7] * y + m[11] * z + m[15] * w;
        out.length = 4;
        return out;
    }
    _vec3TransformMat4(a, m) {
        const out = [0, 0, 0];
        const x = a[0];
        const y = a[1];
        const z = a[2];
        const w = m[3] * x + m[7] * y + m[11] * z + m[15] || 1.0;
        out[0] = (m[0] * x + m[4] * y + m[8] * z + m[12]) / w;
        out[1] = (m[1] * x + m[5] * y + m[9] * z + m[13]) / w;
        out[2] = (m[2] * x + m[6] * y + m[10] * z + m[14]) / w;
        out.length = 3;
        return out;
    }
    _mat4multiply(a, b) {
        const out = [];
        const a00 = a[0];
        const a01 = a[1];
        const a02 = a[2];
        const a03 = a[3];
        const a10 = a[4];
        const a11 = a[5];
        const a12 = a[6];
        const a13 = a[7];
        const a20 = a[8];
        const a21 = a[9];
        const a22 = a[10];
        const a23 = a[11];
        const a30 = a[12];
        const a31 = a[13];
        const a32 = a[14];
        const a33 = a[15];
        let b0 = b[0];
        let b1 = b[1];
        let b2 = b[2];
        let b3 = b[3];
        out[0] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
        out[1] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
        out[2] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
        out[3] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
        b0 = b[4];
        b1 = b[5];
        b2 = b[6];
        b3 = b[7];
        out[4] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
        out[5] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
        out[6] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
        out[7] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
        b0 = b[8];
        b1 = b[9];
        b2 = b[10];
        b3 = b[11];
        out[8] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
        out[9] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
        out[10] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
        out[11] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
        b0 = b[12];
        b1 = b[13];
        b2 = b[14];
        b3 = b[15];
        out[12] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
        out[13] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
        out[14] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
        out[15] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
        return out;
    }
}
exports.DisplaySizeExtractor = DisplaySizeExtractor;
//# sourceMappingURL=DisplaySizeExtractor.js.map