最近在入坑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;
}

Layabox 世界坐标和屏幕坐标互转的更多相关文章

  1. OSG世界坐标转屏幕坐标(转载)

    OSG世界坐标转屏幕坐标 #define M(row,col) m[col * 4 + row] void Transform_Point(double out[4], const double m[ ...

  2. Unity 坐标 转换 详解 World世界坐标 Screen屏幕坐标 View视口坐标 GUI坐标 NGUI坐标 localPosition相对父级坐标

    在制作游戏中我们经常会遇到这样一个需求: 在人物模型的上面显示 名字.称号 一类的文字或者图片 如下图 人物模型属于是Camera1   UI Title信息属于NGUI Camera2 如下图 这时 ...

  3. threejs 世界坐标与屏幕坐标相互转换

    屏幕坐标转世界坐标: let pX = (screenPoint.x / this.scene.renderer.domElement.clientWidth) * 2 - 1; let pY = - ...

  4. ogre世界坐标鱼屏幕坐标相互转换

    bool worldCoordToScreen(Vector3 objPos, Camera* cam, Vector2 screenRect,  Vector2& screenPos) { ...

  5. threejs 世界坐标转化为屏幕坐标

    网站: http://www.yanhuangxueyuan.com/Three.js_course/screen.html 方法.project 通过Vector3对象的方法project,方法的参 ...

  6. u3d 楼梯,圆环,椭圆,直线运动。世界坐标。点击。U3d stair, ring, ellipse, linear motion.World coordinates.Click .

    u3d 楼梯,圆环,椭圆,直线运动.世界坐标.点击. U3d stair, ring, ellipse, linear motion.World coordinates.Click . 作者:韩梦飞沙 ...

  7. 【Python文件处理】递归批处理文件夹子目录内所有txt数据

    因为有个需求,需要处理文件夹内所有txt文件,将txt里面的数据筛选,重新存储. 虽然手工可以做,但想到了python一直主张的是自动化测试,就想试着写一个自动化处理数据的程序. 一.分析数据格式 需 ...

  8. Unity学习疑问记录之坐标体系

    [Unity3D的四种坐标系] 1.World Space(世界坐标):我们在场景中添加物体(如:Cube),他们都是以世界坐标显示在场景中的.transform.position可以获得该位置坐标. ...

  9. (十五)WebGIS中平移功能的设计和实现

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/. 1.前言 这一章我们将详细讲解WebGIS工具栏中另一个基础工具——平 ...

随机推荐

  1. idea转eclipse快捷键

    1.打开idea,点击上方菜单栏中的File, 2.在弹出的setting页面中左侧导航中选择Keymap:在keymaps下拉列表中选择Eclipse:如果想要使用这个快捷键风格,则点击右侧的cop ...

  2. 牛客-Forsaken的数列(Treap)

    题目传送门 sol:第一次看题还真信了是用线段树来做,但是没什么想法,看了题解发现是我不会的Treap,然后花了几天时间学习了一下并补掉题目 无旋Treap #include <bits/std ...

  3. 【UML】

    静态:类图,包图,部署图,构件图,对象图 行为:用例图,活动图,顺序图,状态图,交互图 [类图] http://www.uml.org.cn/oobject/201104212.asp [对象图] h ...

  4. 安装python第三方包

    20190822 先说一下,有4种方法(我知道的): 1.源码安装 2.python自带包管理器安装 3.外部包管理器安装 4.whl格式安装 1.源码安装 Python第三方库几乎都可以在githu ...

  5. Mybatis 常见面试题

    1.什么是Redis?简述它的优缺点? Redis本质上是一个Key-Value类型的内存数据库,很像memcached,整个数据库统统加载在内存当中进行操作,定期通过异步操作把数据库数据flush到 ...

  6. JVM笔记(二)

    内存分配1)对象的内存分配,往大的方向讲,就是在堆上分配2)对象优先在Eden分3)大对象直接进入老年代4)长期存活的对象进入老年代:对象在Survivor区每“熬过”一次Minor GC,年数加1, ...

  7. 吴裕雄--天生自然 oracle学习笔记:Sqlplus连接的时候中文出现乱码“?胧淙胗没?”的解决方案

  8. 吴裕雄--天生自然 人工智能机器学习实战代码:线性判断分析LINEARDISCRIMINANTANALYSIS

    import numpy as np import matplotlib.pyplot as plt from matplotlib import cm from mpl_toolkits.mplot ...

  9. 腾讯云服务器(centos7.2)上安装MySQL

    1.到MySQL官网找到相应的版本 https://dev.mysql.com/downloads/repo/yum/ 找到下面的Linux7,即CentOS7(CentOS是Red Hat旗下的)点 ...

  10. DOS命令编译JAVA程序

    上篇文章给大家写了怎么安装JDK配置,现在这篇文章我们就来学习下怎么在DOS命令下编译JAVA程序,以后没编译器都可以直接编译啦(嘻嘻!) 我这里就用永远的 “Hello wrold!”来演示下吧. ...