jjzjj

Unity --- Vector3的使用,欧拉角与四元数

Metallic Cat 2024-07-16 原文

1.Vector3是啥?

 

 representation of .... (表示...) --- 相对应的vector2就是2d的

Vector3是UnityEngine类下的一个静态结构体,这个结构体中有许多成员方法以及三个最重要的成员变量 : x ,y ,z 均为单精度浮点型float

创建vector3类型的变量的时候有三种初始化方式,一种是什么都不加,如下图

 一种是加两个参数 x ,y,还有种是加三个参数x,y,z

2.通过vector3类型创建的变量可以表示为一个向量,也可以表示为一个坐标(点),还可以表示为一个旋转(表示旋转的时候括号内的参数是旋转角),还还可以表示缩放(x,y,z)三个方向上的缩放

3.在c#中创建一个浮点数的时候,默认为双精度浮点数,如果是想创建一个单精度浮点数的话,我们要在这个浮点数后面加上一个 f ,比如 : 0.5f

4.Vector3结构体中提供了很多静态的属性来帮助我们给vector3变量初始化:比如

vector.zero(把这个赋值给变量,可以直接把变量的参数初始化为(0,0,0))

vector.one ---- (1 , 1, 1 )

 还有back,right,left,up,down等等,到时候可以自己去看看

5.也可以直接通过结构体变量名+ 点操作符 + 成员参数民来访问和操作成员参数

6.通过结构体名调用Vector结构体中的静态方法angle --- 传两个vector变量作为参数 ,方法的返回值是将这两个作为向量时的向量夹角。

如果是调用distance方法的话,传的两个参数会被当作坐标(点),返回值是两个点之间的距离

用Dot方法的话,就是当向量求点乘,返回点乘后的值

如果是Cross方法的话,当向量求叉乘,返回叉乘后得到的新Vector变量

调用Lerp方法的话,要传三个参数,插值中的t参数的范围是0到1,通过这个方法我们可以获得一个沿着固定起点向固定终点不断移动的向量/点/刻度/旋转

 7.直接通过变量调用magnitude(向量模长)属性,可以获得当前向量的模长

调用normalized属性我们可以获得将变量规范化后(单位长度化)的新变量


欧拉角 --- 与旋转有关 

 这个面板中的Rotation中的每一个参数都是欧拉角,范围是0到360°

通过欧拉角控制物体旋转并不是有三个旋转角度参数就足够了,我们还需要一个参数来表示x,y,z三个旋转角度的旋转顺序

原因是通过欧拉角体系来描述旋转时,不同的旋转顺序带来的旋转结果是不一样的

人们认为归定了这个顺序参数是X - Y - Z

然后欧拉角旋转时一个很重要的特点是:

顺序在前的轴转动时会带动顺序在后的轴转动,这是因为欧拉角的旋转原理是相对于改变前的自身坐标系进行旋转的,但是顺序在后的轴转动时顺序在前的轴不会跟着转动

欧拉角的转动其实就是新的自身坐标系(整体)相对于旧的自身坐标系顺/逆时针转动一定的角度(欧拉角:0~360°),比如下面这个:

第一次欧拉角旋转:新的自身坐标系Y轴顺时针相对于旧的自身坐标系Y轴转动(一个轴的转动会带动整个坐标系转动,因为相互垂直的关系要保持)

 第二次欧拉角转动:原本是新的坐标系的Y轴转化为旧的坐标系Y轴,然后在转动的时候生成一个新的坐标系Y轴顺时针相对于旧坐标系Y轴旋转一个欧拉角

( 上面这个描述的是动态定义下的欧拉角,还有一种静态定义下的欧拉角,即相对于世界坐标系转动,但此处我们只讨论动态定义下的欧拉角)

继续回到欧拉角的特征上:即顺序在前的轴转动时会带着顺序在后的轴一起转动,但是顺序在后的轴转动时不会带动顺序在前的轴转动

根据这个特征我们就能够知道万向死锁出现的原因了:

如果我们先转Y轴(X轴和Z轴相互垂直),转动90°,根据上面的特性我们可以得知:X轴不会跟着转动,Z轴会跟着转动90°,此时就会出现一个现象:

Z轴和X轴重合了!!!,此时我们无论是绕X轴转还是绕Z轴转,得到的旋转结构都是一样的

由于发生了重合,三个旋转轴变成了两个,我们的物体丢失了一个旋转角度,或者说丢失了一个自由度

但是,这种论述只是方便解释的假设情况,真正的事实是:无论那个轴发生旋转都会带动另外两个轴发生旋转,那么在这种现实情况下又为什么会发生万向死锁呢?

变换和运动是不相同的!!

从A变为B,我们称为变换,这是两个状态的转变,是没有过程的,上一秒在起点下一秒在终点,这就是变换

而运动是有过程的,是连续的。在现实中,运动是由无数个变换组成的,从A到B的运动过程中我们执行了无数个变换,将这无数个变换的空间积分就成了宏观的距离,无数个时间积分就成了宏观的时间

电脑中的动画就是在模拟现实中的变换来实现运动。在电脑中所有的动画都可以在一定时间里拆分为有限数量的图片,这些图片都在一定的时间间隔内播放(这个时间间隔被称为帧)

上一帧的图片A变为下一帧的图片B,这就是一种变换而不是运动!!!当这些变换在一定时间内积累的足够多的时候就形成了运动(即连续)的假象

而欧拉角描述的就是变换而不是运动!

一个欧拉角变换过程是由三个分变换按照X-Y-Z的顺序组成的一个总变换,这三个分变换分别是:X轴变换,Y轴变换和Z轴变换,这三个变换组成一个总的变换后,得到一个结果姿态,然后我们会将初始姿态直接变为结果姿态

每一次的欧拉角变换都是在给定变换参数和顺序的情况下,将初始姿态变为结果姿态

而每一次的欧拉角变换的初始姿态都是固定的,即参数为0,0,0的情况


 四元数 --- 欧拉角进化版

在系统中表示旋转的一般不是欧拉角而是四元数

四元数是一个四维空间的高阶复数,它的效率很高,而且不会造成万向节死锁问题

WoW,看了半天,哎,先记个四元数旋转计算公式吧:

具体的公式可以自己上网找找 


Unity引擎带给我们的便利

在unity中,提供给了我们一个方法,当我们向这个方法传一个欧拉角的时候,它会放回一个对应的四元数给我们

Quaternion --- 四元数

创建一个四元数对象的方式有很多种,和Vector对象很类似

1.直接用new创建 - new Quaternion(传四个参数,分别是四元数的实部和三个虚部)

2.直接通过类/结构体名来调用四元数类/结构体中的静态属性来直接赋值创建:

identity : 通过这个赋值得到的四元数坐标如下

 3.通过方法转换将一个欧拉角转换为四元数,然后用这个四元数来赋值

方法是Quaternion中的静态方法Euler(欧拉)括号里面可以传三个角度参数,也可以直接传一个欧拉角进去。这个方法的返回值就是通过传进来的欧拉角转换而成的四元数 

4.

 调用这个LookRotation方法可以获得一个四元数

在括号里我们可以只传一个参数也可以传两个参数,当我们只传一个参数forward(向前)向量的时候,我们可以生成一个用来进行旋转的四元数,将这个四元数用于旋转的时候可以让物体的z轴与forward向量重合

也就是说forward向量影响的是Z轴的指向,而另一个upward向量影响的是Z轴的旋转

当我们只传一个upward向量的时候,就会返回一个用于旋转物体的y轴使得其与我们指定的upward向量平行/重合(对齐)的四元数

如果传两个参数的话,返回的就是一个能让物体Z轴和forward向量对齐的同时,让物体的y轴与upward向量对齐的四元数

注意上面进行旋转的都是物体的本地坐标系

LookRotation详解


5.通过四元数转为欧拉角

rotate是一个欧拉角,quaternion是一个四元数变量名,直接通过这个变量名调用Quaternion中euleAngles静态方法后,会将调用这个方法的四元数转换为对应的欧拉角,并将这个欧拉角返回。

有关Unity --- Vector3的使用,欧拉角与四元数的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  3. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  4. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  5. ruby - 在 Ruby 中使用匿名模块 - 2

    假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于

  6. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  7. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  8. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

  9. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

  10. ruby - 在 64 位 Snow Leopard 上使用 rvm、postgres 9.0、ruby 1.9.2-p136 安装 pg gem 时出现问题 - 2

    我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po

随机推荐