最近在入坑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. freeswitch的internal的profile无法启动

    服务器断电重启后,导致freeswitch的internal的profile无法启动 在fs_cli执行 sofia profile internal restart 打印如下信息: [ERR] sw ...

  2. Nginx 反向代理,IP、端口,项目路径变化的问题

    这两天在云上部署公司项目,涉及到nginx反向代理,在部署完成测试,发现在下载文件的时候,无法下载,提示链接被拒绝. 假设nginx代理地址: http://121.53.21.188:9012/we ...

  3. asp.net 获取日期

    //获取日期+时间 DateTime.Now.ToString(); // 2008-9-4 20:02:10 DateTime.Now.ToLocalTime().ToString(); // 20 ...

  4. Python 装饰器 多装饰器同时装饰一个函数 多参数函数

    装饰器是在不修改源代码的情况下,使用装饰器增加原函数的功能. 在软件开发中有一个原则——"开放-封闭",简单地说就是已经实现的功能不允许被修改,但可以被扩展. 封闭:已经实现的功能 ...

  5. windows 不能在本地计算机启动apache2。有关更多信息,查阅系统事件日志。如果这是非Microsoft服务,请与服务厂商联系,并参考特定服务错误代码1

    今天使用apache的时候又无法启动了,之前也遇到过,这次重点说这一次的情况,其他情况可以查看博主apache相关的其他博文:网上关于apache服务端的设置的很多,但是都不适合我的情况: 一般使用a ...

  6. JAVA异常处理原则和log4j输出详细异常分析

    1.多用try,catch;不要一个try,catch包含所有内容 好处:不同模块抓取不同异常,某一模块异常挂了,不影响其他模块的程序的进行 2.多写几个catche:尽量不要使用Exception这 ...

  7. navisworks卸载/完美解决安装失败/如何彻底卸载清除干净navisworks各种残留注册表和文件的方法

    在卸载navisworks重装navisworks时发现安装失败,提示是已安装navisworks或安装失败.这是因为上一次卸载navisworks没有清理干净,系统会误认为已经安装naviswork ...

  8. 3DMAX 卸载工具,完美彻底卸载清除干净3dmax各种残留注册表和文件

    一些同学安装3dmax出错了,也有时候想重新安装3dmax的时候会出现这种本电脑windows系统已安装3dmax,你要是不留意直接安装,只会安装3dmax的附件,3dmax是不会安装上的.这种原因呢 ...

  9. 吴裕雄--天生自然 R语言开发学习:时间序列(续三)

    #-----------------------------------------# # R in Action (2nd ed): Chapter 15 # # Time series # # r ...

  10. 使用nodeJs安装Vue-cli并用它快速构建Vue项目

    部分摘自:http://www.cnblogs.com/wisewrong/p/6255817.html(已在本地测试) 前提:nodeJs本地已安装. 一.安装 vue-cli 1.使用nodeJs ...