Layabox 世界坐標和屏幕坐標互轉


最近在入坑Layabox,花了幾天時間做世界坐標和屏幕坐標的互轉,由於Layabox沒有現成的代碼所以只能自己手動寫,大概就是模仿unity里面的ScreenToWorldPoint和WorldToScreenPoint函數。

大致思路是,屏幕坐標的z軸就是,物體離相機的距離。

需要注意的是,unity 和 layabox 坐標系的區別,三維坐標( unity 左手坐標系, layabox 右手坐標系 ) 和 屏幕坐標系都不同( unity原點在左下角,layabox 原點在右下角 )

https://www.cnblogs.com/mttnor/p/9647850.html 里面的感覺比較明了,參考里面的圖片可以更好的理解我的代碼

/**[SixGod]
     * 世界坐標轉屏幕坐標
     * @param {Laya.Camera} camera   參照相機
     * @param {Laya.Vector3} point   需要轉換的點
     */
    static WorldToScreen2(camera, point) {
        var pointA = this.InverseTransformPoint(camera.transform, point);
        var distance = pointA.z;

        var out = new Laya.Vector3();
        camera.viewport.project(point, camera.projectionViewMatrix, out);
        var value = new Laya.Vector3(out.x / Laya.stage.clientScaleX, out.y / Laya.stage.clientScaleY, distance);
        return value;
    }
/**[SixGod] * 屏幕坐標轉世界坐標 * @param {Laya.Camera} camera 參照相機 * @param {Laya.Vector3} point 需要轉換的點 */ static ScreenToWorld(camera, point) { var halfFOV = (camera.fieldOfView * 0.5) * Math.PI / 180; let height = point.z * Math.tan(halfFOV); let width = height * camera.aspectRatio; let lowerLeft = this.GetLowerLeft(camera.transform, point.z, width, height); let v = this.GetScreenScale(width, height); // 放到同一坐標系(相機坐標系)上計算相對位置 var value = new Laya.Vector3(); var lowerLeftA = this.InverseTransformPoint(camera.transform, lowerLeft); value = new Laya.Vector3(-point.x / v.x, point.y / v.y, 0); Laya.Vector3.add(lowerLeftA, value, value); // 轉回世界坐標系 value = this.TransformPoint(camera.transform, value); return value; } /**[SixGod] * 獲取三維場景和屏幕比例 * @param {Number} width 寬 * @param {Number} height 長 */ static GetScreenScale(width, height) { var v = new Laya.Vector3(); v.x = Laya.stage.width / width / 2; v.y = Laya.stage.height / height / 2; return v; } /**[SixGod] * 獲取相機在 distance距離的截面右下角世界坐標位置 * @param {Laya.Transform} transform 相機transfrom * @param {Number} distance 距離 * @param {Number} width 寬度 * @param {Number} height 長度 */ static GetLowerLeft(transform, distance, width, height) { // 相機在 distance距離的截面左下角世界坐標位置 // LowerLeft var lowerLeft = new Laya.Vector3(); // lowerLeft = transform.position - (transform.right * width); var right = new Laya.Vector3(); transform.getRight(right); Laya.Vector3.normalize(right, right); var xx = new Laya.Vector3(right.x * width, right.y * width, right.z * width); Laya.Vector3.add(transform.position, xx, lowerLeft); // lowerLeft -= transform.up * height; var up = new Laya.Vector3(); transform.getUp(up); Laya.Vector3.normalize(up, up); var yy = new Laya.Vector3(up.x * height, up.y * height, up.z * height); Laya.Vector3.subtract(lowerLeft, yy, lowerLeft); // lowerLeft += transform.forward * distance; var forward = new Laya.Vector3(); transform.getForward(forward); Laya.Vector3.normalize(forward, forward); var zz = new Laya.Vector3(forward.x * distance, forward.y * distance, forward.z * distance); Laya.Vector3.subtract(lowerLeft, zz, lowerLeft); return lowerLeft; } /**[SixGod] * 世界坐標轉相對坐標 * @param {Laya.Transform} origin camera.transform * @param {Laya.Vector3} point 需要轉換的點 */ static InverseTransformPoint(origin, point) { var xx = new Laya.Vector3(); origin.getRight(xx); var yy = new Laya.Vector3(); origin.getUp(yy); var zz = new Laya.Vector3(); origin.getForward(zz); var zz1 = new Laya.Vector3(-zz.x, -zz.y, -zz.z); var x = this.ProjectDistance(point, origin.position, xx); var y = this.ProjectDistance(point, origin.position, yy); var z = this.ProjectDistance(point, origin.position, zz1); var value = new Laya.Vector3(x, y, z); return value; } /**[SixGod] * 相對坐標轉世界坐標 * @param {Laya.Transform} origin camera.transform * @param {Laya.Vector3} point 需要轉換的點 */ static TransformPoint(origin, point) { var value = new Laya.Vector3(); Laya.Vector3.transformQuat(point, origin.rotation, value); Laya.Vector3.add(value, origin.position, value); return value; } /**[SixGod] * 向量投影長度, 向量CA 在向量 CB 上的投影長度 * @param {Laya.Vector3} A * @param {Laya.Vector3} C * @param {Laya.Vector3} B */ static ProjectDistance(A, C, B) { var CA = new Laya.Vector3(); Laya.Vector3.subtract(A, C, CA); var angle = this.Angle2(CA, B) * Math.PI / 180; var distance = Laya.Vector3.distance(A, C); distance *= Math.cos(angle); return distance; } /**[SixGod] * 向量夾角 * @param {Laya.Vector3} ma 向量A * @param {Laya.Vector3} mb 向量B */ static Angle2(ma, mb) { var v1 = (ma.x * mb.x) + (ma.y * mb.y) + (ma.z * mb.z); var ma_val = Math.sqrt(ma.x * ma.x + ma.y * ma.y + ma.z * ma.z); var mb_val = Math.sqrt(mb.x * mb.x + mb.y * mb.y + mb.z * mb.z); var cosM = v1 / (ma_val * mb_val); if (cosM < -1) cosM = -1; if (cosM > 1) cosM = 1; var angleAMB = Math.acos(cosM) * 180 / Math.PI; return angleAMB; }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM