因为要做AR的标记功能,所以就要用到坐标的转换,就总结了一下屏幕坐标、世界坐标、相机坐标之间的转换。

首先说明的是Unity3D遵从Direct3D标准的左手笛卡尔坐标系变换规则。

也就是说:

世界坐标系就是左手笛卡尔坐标系(x,y,z),相机也是左手笛卡尔坐标系(u,v,w),且面向自身坐标系w坐标轴正上方,屏幕以中央为原点,右和上分别为x,y的正方向。

我将工具代码直接上:

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

public class CameraTransformationUtilities : MonoBehaviour

{

public static CameraTransformationUtilities Instance { get; private set; }

protected CameraTransformationUtilities() { }

private void Start()

{

Instance = this;

}

/// 投影矩阵

/// 视点矩阵

/// 列表形式的投影矩阵

/// 列表形式的视点矩阵

/// 要投影的点的引用

/// 要投影的点引用列表

/// 屏幕宽

/// 屏幕高

/// 列表是否以行优先进行矩阵元素的存储

/// 水平翻转

/// 上下翻转

public void UnprojectScreenToWorld(

Matrix4x4 projectionMatrix,

Matrix4x4 viewMatrix,

ref Vector3 p)

{

// 世界坐标->相机坐标, 相机坐标->屏幕坐标 分别需要 viewMatrix和projectionMatrix

Matrix4x4 PV = projectionMatrix * viewMatrix;

// 逆矩阵即为从屏幕到世界的坐标变换,需指定像素深度

p = PV.inverse.MultiplyPoint(p);

}

public void UnprojectScreenToWorld(

IReadOnlyList projection,

IReadOnlyList view,

ref Vector3 p,

bool rowBase = true

)

{

Matrix4x4 projectionMatrix = ConstructMatirx(projection, rowBase);

Matrix4x4 viewMatrix = ConstructMatirx(view, rowBase);

UnprojectScreenToWorld(projectionMatrix, viewMatrix, ref p);

}

public void UnprojectScreenToWorld(

IReadOnlyList projection,

IReadOnlyList view,

ref Vector3 p,

float width,

float height,

bool rowBase = true,

bool flipLeftToRight = false,

bool flipUpsideDown = false

)

{

Matrix4x4 projectionMatrix = ConstructMatirx(projection, rowBase);

Matrix4x4 viewMatrix = ConstructMatirx(view, rowBase);

ScreenSpaceTransform(ref p, width, height, flipLeftToRight, flipUpsideDown);

UnprojectScreenToWorld(projectionMatrix, viewMatrix, ref p);

}

public void UnProjectScreenToWorld(

Matrix4x4 projectionMatrix,

Matrix4x4 viewMatrix,

ref List pl

)

{

Matrix4x4 PV = projectionMatrix * viewMatrix;

for (int i = 0; i < pl.Count; i++)

{

pl[i] = PV.inverse.MultiplyPoint(pl[i]);

}

}

public void UnProjectScreenToWorld(

IReadOnlyList projection,

IReadOnlyList view,

ref List pl,

float width,

float height,

bool rowBase = true,

bool flipLeftToRight = false,

bool flipUpsideDown = false

)

{

Matrix4x4 projectionMatrix = ConstructMatirx(projection, rowBase);

Matrix4x4 viewMatrix = ConstructMatirx(view, rowBase);

Matrix4x4 PV = projectionMatrix * viewMatrix;

ScreenSpaceTransform(ref pl, width, height, flipLeftToRight, flipUpsideDown);

for(int i = 0; i < pl.Count; i++)

{

pl[i] = PV.inverse.MultiplyPoint(pl[i]);

}

}

///

/// 获得相机的世界坐标,遵从 Direct3D 标准的左手笛卡尔坐标系。

///

/// 视点矩阵

///

public Vector3 GetCameraPosition(Matrix4x4 viewMatrix)

{

Matrix4x4 invV = viewMatrix.inverse;

return new Vector3(invV.m30, invV.m31, invV.m32);

}

///

/// 获得相机的世界坐标,遵从 Direct3D 标准的左手笛卡尔坐标系。

///

/// 视点矩阵元素列表

/// 列表是否以行优先进行矩阵元素的存储

///

public Vector3 GetCameraPosition(IReadOnlyList view, bool rowBase = true)

{

Matrix4x4 viewMatrix = ConstructMatirx(view, rowBase);

Matrix4x4 invV = viewMatrix.inverse;

return new Vector3(invV.m30, invV.m31, invV.m32);

}

///

/// 获得相机的视线方向,遵从 Direct3D 标准的左手笛卡尔坐标系。

///

/// 视点矩阵

///

public Vector3 GetCameraViewDirection(Matrix4x4 viewMatrix)

{

Matrix4x4 invV = viewMatrix.inverse;

return new Vector3(invV.m20, invV.m21, invV.m22);

}

///

/// 获得相机的视线方向,遵从 Direct3D 标准的左手笛卡尔坐标系。

///

/// 视点矩阵元素列表

/// 列表是否以行优先进行矩阵元素的存储

///

public Vector3 GetCameraViewDirection(IReadOnlyList view, bool rowBase = true)

{

Matrix4x4 viewMatrix = ConstructMatirx(view, rowBase);

Matrix4x4 invV = viewMatrix.inverse;

return new Vector3(invV.m20, invV.m21, invV.m22);

}

///

/// 将屏幕点坐标转换成以屏幕中心为原点,

/// 右和上分别为x,y正方向,

/// -1到1的坐标

///

/// 屏幕宽或高

/// 像素坐标(指定宽则为横坐标,指定高则为纵坐标)

/// 是否翻转(Unity通常情况下会将纵坐标翻转)

///

public void ScreenSpaceTransform(ref Vector3 p, float width, float height, bool flipLeftToRight = false, bool flipUpSideDown = false)

{

p.Set((p.x / width * 2 - 1) * (flipLeftToRight ? -1 : 1),

(p.y / height * 2 - 1) * (flipUpSideDown ? -1 : 1),

p.z);

}

public void ScreenSpaceTransform(ref List pl, float width, float height, bool flipLeftToRight = false, bool flipUpSideDown = false)

{

for(int i = 0; i

{

pl[i].Set((pl[i].x / width * 2 - 1) * (flipLeftToRight ? -1 : 1),

(pl[i].y / height * 2 - 1) * (flipUpSideDown ? -1 : 1),

pl[i].z);

}

}

///

/// 从列表中构造Matirx4x4矩阵

///

/// 矩阵元素列表

/// 列表是否以行优先进行矩阵元素的存储

///

public Matrix4x4 ConstructMatirx(IReadOnlyList elements, bool rowBase = true)

{

if (elements.Count != 16) return Matrix4x4.identity;

Matrix4x4 mat = new Matrix4x4();

if (rowBase)

{

mat.m00 = elements[0];

mat.m01 = elements[1];

mat.m02 = elements[2];

mat.m03 = elements[3];

mat.m10 = elements[4];

mat.m11 = elements[5];

mat.m12 = elements[6];

mat.m13 = elements[7];

mat.m20 = elements[8];

mat.m21 = elements[9];

mat.m22 = elements[10];

mat.m23 = elements[11];

mat.m30 = elements[12];

mat.m31 = elements[13];

mat.m32 = elements[14];

mat.m33 = elements[15];

}

else

{

mat.m00 = elements[0];

mat.m10 = elements[1];

mat.m20 = elements[2];

mat.m30 = elements[3];

mat.m01 = elements[4];

mat.m11 = elements[5];

mat.m21 = elements[6];

mat.m31 = elements[7];

mat.m02 = elements[8];

mat.m12 = elements[9];

mat.m22 = elements[10];

mat.m32 = elements[11];

mat.m03 = elements[12];

mat.m11 = elements[13];

mat.m23 = elements[14];

mat.m33 = elements[15];

}

return mat;

}

}

坐标的转换,用的地方特别多,尤其是屏幕划线展示在世界坐标中,我把他形成了工具,直接可以用。

unity 坐标系转换_Unity3D之笛卡尔坐标系转换——屏幕坐标转换世界坐标,世界坐标转换相机坐标工具...相关推荐

  1. 经纬度与地心笛卡尔坐标系转换

    个人随笔 (Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu) 经纬度与笛卡尔坐标系转换,转换的几何计算并不复杂,不过不推理一遍的话,始终是理解的不够透彻.所 ...

  2. 印章识别--笛卡尔坐标系转换成极坐标系

    #代码,使用了opencv自带的函数linearPolar import cv2 import numpy as npsource = cv2.imread('images/image.jpg', 1 ...

  3. 笛卡尔坐标系和Frenet坐标系

    笛卡尔坐标系和Frenet坐标系 Frenet坐标系,自动驾驶"混乱"的源头 [自动驾驶]运动规划丨轨迹规划丨Frenet坐标转换 [自动驾驶]笛卡尔坐标系和frenet坐标系相互 ...

  4. 拉普拉斯算子从笛卡尔坐标系到圆柱坐标系下的推导过程

    这段时间推导圆膜振动方程的时候,需要将振动方程从笛卡尔坐标系转换到圆柱坐标系.虽然这个结果书上都有了,但是不满足于直接给出的结果,想自己推导一下.于是就有了下面的内容.总结起来:就是将笛卡尔坐标系下的 ...

  5. 双球坐标系_坐标系为啥有多种,笛卡尔坐标系、柱坐标系、球坐标系都有啥区别...

    什么是坐标系 坐标系,是理科常用辅助方法.为了说明质点的位置.运动的快慢.方向等,必须选取其坐标系.在 参照系 中,为确定空间一点的位置,按规定方法选取的有次序的一组数据,这就叫做"坐标&q ...

  6. Frenet坐标系及其与笛卡尔坐标的转换(2)——原理

    目录 文章目录 目录 4.1.3 推导 s ˙ \dot{s} s˙ 4.1.4 推导 l ′ ′ l'' l′′ 4.1.5 推导 s ¨ \ddot{s} s¨ 4.1.6 推导 l ¨ \ddo ...

  7. Frenet坐标系及其与笛卡尔坐标的转换(1)——原理

    目录 文章目录 目录 1 Frenet坐标系 2 Frenet坐标系基本概念 3 位置:笛卡尔与Frenet坐标点位置的转换 3.1 位置:笛卡尔坐标 -> Frenet坐标 3.1.1 求解 ...

  8. unity 坐标系转换_Unity的几种坐标系及相互转换

    介绍 1.WorldSpace(世界坐标系) 当我们向场景中添加物体时,他们都是以世界坐标系的方式的方式显示在场景中的 通过transform.position可以得到它在世界中的坐标位置,trans ...

  9. 笛卡尔坐标系_Shader学习(4)坐标系和矢量的概念

    文中多有引用,如有侵权请指出. 坐标系和矢量的概念 1. 笛卡尔坐标系 (1) 在三维游戏的实现中,所有的物体和图像都在笛卡尔坐标系的基础上实现. (2) 二维坐标系和三维坐标系,这些知识在高中时期就 ...

最新文章

  1. JSP与Web技术概论
  2. SAP MM Purchasing Report中Selection Parameter WE101 WE103
  3. NOIp #2010
  4. WINDOWS 几种坐标系
  5. 从网络访问计算机不能添加用户名,windows7 和 XP 能互相用\\ip访问,但是不能通过计算机名访问...
  6. Java导入导出Excel工具类ExcelUtil
  7. 2952 细胞分裂 2
  8. PDFlib TET Crack,文本提取工具包
  9. 美通企业日报 | 阿迪发布星战系列球鞋;安进27亿美元收购百济神州20.5%股份
  10. 华硕飞行堡垒atk驱动在哪_11月8日华硕再撒大额福利 满减优惠价机不可失_第1页...
  11. 面试:list集合去重
  12. Ant Design Vue 菜单刷新后保持菜单选中/点击菜单,收起其他展开的所有菜单,保持菜单聚焦简洁
  13. 从社区报告看未来20年美国AI研究战略
  14. 微信小程序 登陆过期,请重新授权
  15. 分析、归纳、综合、演绎
  16. R费希尔精确检验(Fisher‘s exact test)
  17. redis 学习笔记
  18. nginx本地代理调试微信登录(window版本)
  19. 基于VUE的SVG动画处理(一)
  20. AI 人工智能学习路线

热门文章

  1. Javascript(JS) leetcode 279. 完全平方数
  2. 冒泡排序(Bubble Sort)的学习
  3. ubuntu下禁止TeamViewer开机自启分析
  4. iOS视频下载遇到的问题(附上AFHTTPRequestOperation下载视频方法)
  5. 应届毕业/临时访深码工深圳居住计划
  6. 3G手机Android应用开发视频教程_黎活明老师的视频下载地址(总共有八天课程)
  7. 秒懂!!单臂路由!网络如此简单
  8. 影视编导必备三项知识
  9. 软件研发管理经验总结-管理细分
  10. 程序人生:老板要求“996工作制” 你该怎么办?