Unity中坐标系转换方法
前言
本篇文章主要是参考《Unity API 解析》---陈泉宏。
这是本人在学校图书馆找到一本书,主要介绍的就是常用的类,比较实用,没有冗余的地方。在此推荐一下这本书!
一、ScreenToViewportPoint方法
1、函数原型
public Vector3 ScreenToViewportPoint(Vector3 position);
其中参数position为屏幕参考点。
2、功能说明
可以实现坐标点position从屏幕坐标系向摄像机视口的单位化坐标系转换。参考点position的x和y分量为屏幕的实际坐标值,单位为像素,z值无效。
3、实例演示
using UnityEngine;
using System.Collections; public class ScreenToViewportPoint_ts : MonoBehaviour { // Use this for initialization
void Start () { transform.position = new Vector3(0.0f, 0.0f, 1.0f);
transform.rotation = Quaternion.identity;
//从屏幕的实际坐标向视口的单位化比例值转换
Vector3 viewPortPoint = camera.ScreenToViewportPoint(new Vector3(Screen.width / 2.0f, Screen.height / 2.0f, 100.0f));
Debug.Log("转换后的摄像机视口坐标系的坐标: " + viewPortPoint);
//从视口的单位化比例值向屏幕的实际坐标点转换
Vector3 screenPoint = camera.ViewportToScreenPoint(viewPortPoint);
Debug.Log("转换后的屏幕坐标: " + screenPoint);
Debug.Log("屏幕宽: " + Screen.width + " 屏幕高: " + Screen.height); } // Update is called once per frame
void Update () { }
}
4、运行结果
二、ScreenToWorldPoint方法
1、函数原型
public Vector3 ScreenToWorldPoint(Vector3 position);//position是参考点
2、功能说明
将参考点position从屏幕坐标系转换到世界坐标系。position中各个分量值都为实际单位像素值,而非比例值。
Vector3 v = camera.ScreenToWorldPoint(ps);//ps为参考点
//v的各个分量值为
v.x = camera.transform.position.x + ps.z*asp*tan(e/);
v.y = camera.transform.position.y + ps.z*tan(e/);
v.z = camera.transform.position.z + ps.z;
其中e为摄像机的视口夹角fieldOfView的值,asp为摄像机视口的宽高比例值aspect。具体了解可以参考3D游戏与计算机图形学中的数学方法-视截体
3、实例演示
using UnityEngine;
using System.Collections; public class ScreenToWorldPoint_ts : MonoBehaviour
{ // Use this for initialization
void Start () { transform.position = new Vector3(0.0f, 0.0f, 1.0f);
camera.fieldOfView = 60.0f;
camera.aspect = 1.6f;
Debug.Log("z轴正方向100单位处对应的屏幕左下角的世界坐标值: " + camera.ScreenToWorldPoint(new Vector3(0.0f,0.0f,100.0f)));
Debug.Log("z轴正方向100单位处对应的屏幕中间的世界坐标值: " + camera.ScreenToWorldPoint(new Vector3(Screen.width / 2.0f, Screen.height / 2.0f, 100.0f)));
Debug.Log("z轴正方向100单位处对应的屏幕右上角的世界坐标值: " + camera.ScreenToWorldPoint(new Vector3(Screen.width, Screen.height, 100.0f))); } // Update is called once per frame
void Update () { }
}
4、运行结果
三、ViewportToWorldPoint方法
1、函数原型
public Vector3 ViewportToWorldPoint(Vector3 position);
2、功能说明
可以实现从Camera视口坐标点到世界坐标点转换,与WorldToViewportPoint的功能正好相反。此方法的返回值大小受当前Camera在世界坐标系中的位置、fieldOfVieew值以及参考点position的共同影响。其中参考点position的x和y分量的有效范围为[0.0,1.0],位比例值;而z值为实际单位值,而非比例值。
视口坐标点与世界坐标点的转换公式:
假设ps是视口坐标点,v是转换后对应ps的世界坐标点。那么有如下方程式:
v.x = camera.transform.position.x + K1;
v.y = camera.transform.position.y + K2;
v.z = camera.transform.position.z + ps.z;
其中K1 = ps.z * asp * ((ps.x -0.5)/0.5)*tan(e/);
K2 = ps.z * ((ps.y -0.5)/0.5)*tan(e/);
e位摄像机的视口夹角fieldOfView的值,asp为摄像机视口的宽高比aspect。
3、实例演示
using UnityEngine;
using System.Collections; public class ViewportToWorldPoint_ts : MonoBehaviour { // Use this for initialization
void Start () { transform.position = new Vector3(1.0f, 0.0f, 1.0f);
camera.fieldOfView = 60.0f;
camera.aspect = 16.0f / 10.0f;
Debug.Log("屏幕左下角: " + camera.ViewportToWorldPoint(new Vector3(0.0f, 0.0f, 100.0f)));
Debug.Log("屏幕中间: " + camera.ViewportToWorldPoint(new Vector3(0.5f, 0.5f, 100.0f)));
Debug.Log("屏幕右上角: " + camera.ViewportToWorldPoint(new Vector3(1.0f, 1.0f, 100.0f))); } // Update is called once per frame
void Update () { }
}
4、运行结果
其余还有WorldToScreenPoint、WorldToViewportPoint等方法,使用如上面的例子类似,在此就不做阐述了。
四、关于Camera视口、aspect、pixelRect及Rect的解释
- Camera视口用来记录当前摄像机能看到场景中的哪些内容,其大小及位置是可以改变的。而屏幕视口是指当前的硬件的屏幕,对于一个固定的硬件,它的屏幕视口大小(即分辨率)是固定的。Camera视口的内容不一定可以完全显示在屏幕上,屏幕可能只显示了一部分视口内容,也可能对视口内容进行了放缩。可以简单的理解为Camera视口是一张二维图片,而屏幕是用来显示这张图片的,图片可以被剪切,也可能被压缩。
- Unity的Game面板中的aspect选项是用来模拟硬件屏幕的,可以分为三类即全屏显示、固定比例显示和固定分辨率显示。全屏显示即以当前Camera屏幕的大小来模拟硬件屏幕分辨率,其Camera视口即为当前摄像机的默认状态。而在固定比例方式则会改变Camera视口的宽高比,其大小不固定。而在固定分辨率方式下,其有效显示区间将保持固定分辨率的大小。
Camera屏幕分辨率的设置方式
- 在Camera.aspect固定的情况下,无论选择Game视图中哪种屏幕模拟方式,它们的显示内容都是相同的。不同的屏幕模拟方式只会对显示的内容进行放缩。决定屏幕视口显示内容的是Camera.aspect的值和Camera.transform的属性,至于屏幕要如何显示Camera视口的内容,那就是硬件显示屏要处理的事情了。
- PixelRect和Rect功能类似,都是决定硬件显示屏如何显示Camera视口提供的内容的。不同的是PixelRect是以实际像素来展示显示内容,而Rect是以单位化形式展示显示内容。
Unity中坐标系转换方法的更多相关文章
- 关于Unity中坐标系的种类
坐标空间 1:物体空间: 3D物体自己的坐标空间 一般设计时几何体以中心为原点,人物以双脚为原点; 2: 世界空间: 3D物体在场景中的世界坐标, 整个游戏场景的空间; 3: 摄像机空间: 以观察摄像 ...
- maya和Unity中的坐标系旋转
maya软件是用的右手坐标系,默认旋转顺序是ZYX,即先绕Z轴旋转,再绕Y轴旋转,最后绕X轴旋转. 比如在maya软件中,右侧的旋转顺序是可选的,默认的选择是“XYZ”,其实物体旋转顺序是倒着念,即上 ...
- Unity 中的坐标系
说明: 注意几点: 0 行向量右乘矩阵与列向量左乘矩阵,两个矩阵互为逆矩阵 1 法线转换与mul,mul函数左乘矩阵当列矩阵计算,右乘当行矩阵计算 2 叉乘与左右手系,左手系用左手,右手系用右手,ax ...
- 解读Unity中的CG编写Shader系列八(镜面反射)
转自http://www.itnose.net/detail/6117378.html 讨论完漫反射之后,接下来肯定就是镜面反射了 在开始镜面反射shader的coding之前,要扩充一下前面提到的知 ...
- 解读Unity中的CG编写Shader系列三
转自http://www.itnose.net/detail/6096068.html 在上一个例子中,我们得到了由mesh组件传递的信息经过数学转换至合适的颜色区间以颜色的形式着色到物体上.这篇文章 ...
- unity中的欧拉角
unity中欧拉角用的是heading - pitch -bank系统(zxy惯性空间旋转系统):当认为旋转顺序是zxy时,是相对于惯性坐标系旋转.当认为旋转顺序是yxz时,是相对于物体坐标系旋转. ...
- 【Unity编程】Unity中的欧拉旋转
欧拉角的定义 在写这篇博客之前,我搜索了网上很多关于欧拉角的定义,发现大部分引用自维基百科的定义,我这里也引述一下: 维基百科定义 莱昂哈德·欧拉用欧拉角来描述刚体在三维欧几里得空间的取向.对于任何参 ...
- 骨骼动画的原理及在Unity中的使用
制作骨骼动画 我们看看这几步操作后,我们得到了那些数据: 1.每个皮肤顶点的初始世界坐标. 2.每个骨骼关节顶点的初始世界坐标. 3.每个顶点被骨骼顶点的影响信息. 4.骨骼如何移动. 骨骼动画原理 ...
- unity中camera摄像头控制详解
目录 1. 缘起 2. 开发 2.1. 建立项目 2.2. 旋转 2.2.1. 四元数 2.3. 移动 2.3.1. 向量操作 2.4. 镜头拉伸 2.5. 复位 2.6. 优化 1 缘起 我们的产品 ...
随机推荐
- angular.js ng-repeat动态插入删除dom节点
既然上面提到 angular.js 下无需用户直接操作dom ,而是在编译间断 dom 与 控制层model 实现了双向绑定,一方做出改变,另一方就会立即改变,那问题来了,我想插入一个文本框和按钮,并 ...
- error: expected expression before 'struct'
错误原因: 使用了offsetof函数,却没有包含头文件<stddef.h> 解决办法: 包含<stddef.h>
- DMA2D 图形加速器简介
在实际使用 LTDC 控制器控制液晶屏时,使 LTDC 正常工作后,往配置好的显存地址写入要显示的像素数据, LTDC 就会把这些数据从显存搬运到液晶面板进行显示,而显示数据的容量非常大,所以我们希望 ...
- bnuoj16491
http://www.bnuoj.com/bnuoj/problem_show.php?pid=16491 题意:有t组测试数据,每组测试数据第一行为n,m,接下来有n种跑法,m为最大的能力,每一种跑 ...
- poj1509(环形字符串求最小字典序)
题意:给你一串字符串,但是这串字符串是环形的,让你找个位置切开,使得它的字典序最小....... 思路:典型的最小表示法....... #include<iostream> #includ ...
- JavaScript高级 面向对象(4)--值类型和引用类型
说明(2017.3.30): 1. 变量只存数据本身就是值类型,如var a = 123, var a = "123"; 变量存的是一个引用,数据存在别的地方,就是引用类型,如数 ...
- PHP中Array的hash函数实现
PHP中使用最多的非Array莫属了,那Array是如何实现的? 在PHP内部Array通过一个hashtable来实现,其中使用链接法解决hash冲突的问题,这样最坏情况下,查找Array元素的复杂 ...
- 【Android】使用Pull生成/解析XML文件
一.生成XML文件,即是将对象集合转为XML文件存储. 对象集合 –> XML(序列化) Android中使用android.util.Xml类对其进行了描述,提供相应的API. 步骤大致如下: ...
- eclipse中使用maven创建项目JDK版本默认是1.5解决方法
请看解决方案: 1. 修改maven的settings.xml文件. 添加以下行,jdk版本改为自己需要的版本: <profile> <id>jdk-1.7</id> ...
- JVM中的垃圾回收
GC 垃圾回收回收什么 Java的内存分配原理与C/C++不同.C/C++每次申请内存时都要malloc进行系统调用.而系统调用发生在内核空间,每次都要中断进行切换,这须要一定的开销. 而Java虚拟 ...