最近在入坑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. 关于vyos 防火墙配置

    VyOS是一个基于Debian的网络操作系统,是Vyatta的社区fork.Vyatta是博通的企业级的产品,通过这套系统,能在x86平台提供路由,防火墙和×××的功能. 这个系统提供了和其他诸如Ci ...

  2. LiauidCrystal

    1.begin()函数语法: lcd.begin(cols,rows) cols:列数: rows:行数: 2.print()函数,语法: lcd.print(data) lcd.print(data ...

  3. MySQL表查询

    单表查询 表准备 create table emp( id int not null unique auto_increment, name ) not null, sex enum('male',' ...

  4. jmeter测试get post 笔记

    0 环境 系统环境:win7 1 操作 1 post 新建线程组 2 get 和post新建类似 http请求 只是新建一个参数化我测试的2个url http://127.0.0.1:8080/cry ...

  5. Xshell中使用xftp怎么选择默认编辑器,如nodepad

    工具-选项-高级-编辑器路径

  6. 如何使用iTunes制作iPhone铃声

    新版iTunes(iTunes11)推出以后,界面上发生了一些改变,给人带来一种面貌一新的感觉,但也给许多朋友带来一些操作上的不太适应.下面就大家比较关心的iPhone的铃声制作方法,我在iTunes ...

  7. Java IO: 其他字节流(上)

    作者: Jakob Jenkov 译者: 李璟(jlee381344197@gmail.com) 本小节会简要概括Java IO中的PushbackInputStream,SequenceInputS ...

  8. HDU-3579-Hello Kiki (利用拓展欧几里得求同余方程组)

    设 ans 为满足前 n - 1个同余方程的解,lcm是前n - 1个同余方程模的最小公倍数,求前n个同余方程组的解的过程如下: ①设lcm * x + ans为前n个同余方程组的解,lcm * x ...

  9. 原创:CentOS 环境中 Zabbix 3.4 的安装部署实践

    IT管理工作中,如果没有对服务器.网络设备.服务.进程.应用等的监控,往往是用户发送问题报告后才知道出了问题.事后救火显得被动,不能从容面对问题. 才有了部署一套网络监控系统的想法,机缘巧合下结识了Z ...

  10. 吴裕雄--python学习笔记:爬虫包的更换

    python 3.x报错:No module named 'cookielib'或No module named 'urllib2' 1. ModuleNotFoundError: No module ...