三维空间旋转和Three.JS中的实现
三维空间中主要有两种几何变换,一种是位置的变换,位置变换和二维空间的是一样的。假设一点P(X1,Y1,Z1) 移动到Q(X2,Y2,Z2)只要简单的让P点的坐标值加上偏移值就可以了。但是三维空间的旋转变换就不能简单的使用二维空间的变换了。下面详细介绍一下三维空间的旋转。
三维空间的旋转:
二维空间的旋转可以看作是围绕点的旋转,只有一个自由度。而三维空间的旋转是围绕一条线旋转的。当旋转的轴是Z轴时,旋转可以看作是在二维平面XY平面的旋转,旋转的中心点是P(x=0,y=0)。按照右手法则,让拇指指向Z轴的正方向,四指指向为旋转的正方向。按照Y轴和X轴的旋转也类似。按照不同的轴的旋转可以进行组合。比如,先按照Z轴旋转45度,再按照Y轴旋转45度。但是每一个朝向都可以看成是物体在原始位置处围绕某一个轴转动了一个角度形成的。
三维空间的旋转有多种方式,如旋转矩阵,欧拉角,四元数:
1 .欧拉角(Euler Angle)
欧拉角这种旋转方式是最直观的,因为这种方式是将旋转表示为物体按坐标系的三个轴X(1,0,0) ,Y(0,1,0),Z(0,0,1)的旋转组合成的。这里首先要明确两个概念,1参考系:类似于物理中的参考系,是静止不动的,比如北极星,不管在那里,那就是北。2坐标系:坐标系是固定于物体的,随着物体的转动而发生变化,最简单的例子就是左右,人所说的左边一直是根据人所面对的方向来决定的。在下图中蓝色为参考系的三个轴,而红色是物体的坐标系的三个轴。虽然说欧拉角表示的旋转是有多个沿坐标轴的旋转组合而成的。但是旋转的顺序不同旋转就不同,所以,欧拉角中旋转的顺序要注明。这里的三个角是zxz顺规的欧拉角。物体先绕Z轴旋转了α°,然后物体坐标系的x轴的位置变化到了图中N的位置,然后绕这个N轴(X轴)旋转β°,最后再沿Z轴旋转γ°。

欧拉角的旋转虽然是最直观的,但是却存在一个非常致命的问题--万向节锁,大致是指。按某一个旋转了90°的时候会使另外两个轴重合,从而丧失一个自由度。无法很好的追踪物体。具体的可以看一下这个视频万向节锁。讲得非常清楚,这里也就不再赘述了。
欧拉角旋转应用于很多第一人称3D游戏中,虽然万向节锁是无法避免的,但可以将触发的概率减至最小。只有当人物视线完全朝上或者朝下的时候才会触发万向节锁。
2 .旋转矩阵(Rotation Matrix)
三维空间的旋转使用旋转矩阵的方式表示比较容易,旋转矩阵是一个3x3的矩阵。可以看作物体沿空间中的某一个轴(x,y,z)旋转了θ°。三维的旋转矩阵可以表示为:
![]()
其中:c=cos(θ) , s=sin(θ),t=1-cos(θ)
假设物体在初始位置的旋转矩阵为A ,经过旋转之后的旋转矩阵为A` ,那么A,A`以及R之间的关系可以表示为 A` = AR。
3 .四元数(Quaternion)
四元数是一种高阶复数,四元数q表示为:q =(x,y ,z ,w)=xi+y j+z k+w 可以将四元数写成一个向量和一个实数的组合。q =(v ⃗ +w)=((x,y ,z ),w) ,四元数也可用矩阵表示。
![]()
可以证明这个矩阵和旋转矩阵是一个矩阵。
在数学上四元数来表示的旋转要好一些,但是在程序设计里,旋转矩阵更方便。在Three.js中使用四元数的方式也是将四元数换成了旋转矩阵使用的。
Three.JS中的旋转实现
three.js支持上面所说的三种旋转方式。
1.欧拉角
three.js中场景里的物体都属于Object3D这个类。这个类中有表示物体朝向的一个属性–rotation,这是一个欧拉类型的值,有三个轴旋转的角度,单位是π,还有一个旋转的顺序组成。要使物体旋转可以改动这个rotation的值。比如让物体按Y轴正方向旋转45°可以写成 object3D.rotation.y+=0.25*Math.PI。这里的旋转顺序默认使用的是‘XYZ’顺序。另外Object3D 还提供了几个方法来进行旋转,rotateX(angle),rotateY(angle),rotateZ(angle),分别是按照X,Y,Z轴的正反向旋转一个角度。但具体使用的时候和 object3D.rotation.y+=0.25*Math.PI 这种方式还是有一些区别的。另外还有一个方法是rotateOnAxis(axis,angle) 可以指定旋转的轴,这里的axis是一个Vector3类型的值。
2.矩阵
three.js里的矩阵和之前介绍的不太一样,因为three.js里的矩阵式一个4x4的复合的矩阵(Transform Matrix),将位置信息放在了矩阵的最后一行。可以很容易的从这个矩阵里分解出旋转矩阵(Rotation Matrix),和位置矩阵(Translation Matrix)。Matrix4的主要方法有:
mutiply():矩阵的乘法。
transpose() :矩阵转置。
getInverse(m) :求逆矩阵。
makeRotationFromEuler(euler) :通过一个欧拉类型的值来设置矩阵的值。
makeRotationFromQuaternion(q):通过一个四元数类型的值来设置矩阵。
makeRotationonAxis(axis,theta):按一个轴旋转θ°,然后设置矩阵的值。
makeRotationonAxis(axis,theta) 的源码为:
makeRotationAxis: function ( axis, angle ) { var c = Math.cos( angle ); var s = Math.sin( angle ); var t = 1 - c; var x = axis.x, y = axis.y, z = axis.z; var tx = t * x, ty = t * y; this.set( tx * x + c, tx * y - s * z, tx * z + s * y, 0, tx * y + s * z, ty * y + c, ty * z - s * x, 0, tx * z - s * y, ty * z + s * x, t * z * z + c, 0, 0, 0, 0, 1 ); return this; } |
通过源码,可以看出,调用这个方法就可以得到一个旋转矩阵了。然后,让物体的矩阵乘旋转矩阵就可以得到物体转动后的矩阵了。
下面是一段我使用旋转矩阵来旋转物体的代码。
var rotWorldMatrix; function rotateAroundWorldAxis(object, axis, radians) { rotWorldMatrix = new THREE.Matrix4(); rotWorldMatrix.makeRotationAxis(axis.normalize(), radians); rotWorldMatrix.multiply(object.matrix); // pre-multiply object.matrix = rotWorldMatrix; object.rotation.setFromRotationMatrix(object.matrix); } |
通过这样的方法,就可以让物体沿参考系中的确定的一个轴进行旋转了。
3.四元数
没有使用四元数,所以没有研究,在object3D中设置rotation可以通过Matrix ,也可以通过Quaternion ,不过setFromRotationQuaternion的内部也是用的Matrix。
参考资料
https://www.fastgraph.com/makegames/3drotation/
http://www.essentialmath.com/GDC2012/GDC2012_JMV_Rotations.pdf
三维空间旋转和Three.JS中的实现的更多相关文章
- three.js中物体旋转实践之房门的打开与关闭
看这篇博客,默认你已经知道了3D模型实现三维空间内旋转的实现方式(矩阵.欧拉角.四元数). ok,下面正式切入主题,房门的打开和关闭,先上图: 正如你所看到的那样,这个“房门”已经被打开了. 一.th ...
- JS中的自执行函数
本来规划的是2013年,狠狠的将JS学习下,谁知计划赶不上变化,计划泡汤了.13年的我对JS来说可以说是属于跟风,对它的理解和认识也仅仅是皮毛而已,也是因为要完成<ArcGIS API for ...
- js中内置有对象
statpot:使用mongo+bootstrap+highcharts做统计报表 最近做了一个统计项目,这个统计项目大致的需求是统计接口的访问速度.客户端会调用一个接口来记录接口的访问情况,我的需求 ...
- 4.three.js中的坐标系
Three.js中的坐标系 three.js中坐标系使用的是左手坐标系 左手坐标系和右手坐标系的对比: 当然three.js中使用的是右手坐标系 three.js中的旋转的定义 但是three.js中 ...
- Three.js 中的参数调试控制插件dat.GUI.JS - [Three.js] - [dat.GUI]
不论是处于特殊功能的需要,还是处于效果调试方便,我们可能都需要修改模型中的参数值.在Three.js中,谷歌提供了一个js库,即dat.GUI.js用于处理这种需求. 通过该库,我们就不需要通过手动修 ...
- three.js中的矩阵变换(模型视图投影变换)
目录 1. 概述 2. 基本变换 2.1. 矩阵运算 2.2. 模型变换矩阵 2.2.1. 平移矩阵 2.2.2. 旋转矩阵 2.2.2.1. 绕X轴旋转矩阵 2.2.2.2. 绕Y轴旋转矩阵 2.2 ...
- 5.0 JS中引用类型介绍
其实,在前面的"js的六大数据类型"文章中稍微说了一下引用类型.前面我们说到js中有六大数据类型(五种基本数据类型 + 一种引用类型).下面的章节中,我们将详细讲解引用类型. 1. ...
- 【repost】JS中的异常处理方法分享
我们在编写js过程中,难免会遇到一些代码错误问题,需要找出来,有些时候怕因为js问题导致用户体验差,这里给出一些解决方法 js容错语句,就是js出错也不提示错误(防止浏览器右下角有个黄色的三角符号,要 ...
- JS中给正则表达式加变量
前不久同事询问我js里面怎么给正则中添加变量的问题,遂写篇博客记录下. 一.字面量 其实当我们定义一个字符串,一个数组,一个对象等等的时候,我们习惯用字面量来定义,例如: var s = &quo ...
随机推荐
- 一些新的ideas
k-means可以在不同的聚类点间加入计算该方向类内方差的方法改进,可以获得更好的效果: 可以通过爬虫方法在facebook上爬取与happy.sad相关的图片进行图片情感分类,并通过语义分析的方法提 ...
- 解决Oracle在scott用户下创建视图(VIEW)权限不足的方法
问题描述:在scott用户下创建视图的时候,报错:权限不足.(其他用户以此类推)解决方法: 以dba用户登录 sqlplus / as sysdba 赋予scott用户创建VIEW的权限 grant ...
- 基于Bootstrap的JQuery TreeView树形控件,数据支持json字符串、list集合(MVC5)<二>
上篇博客给大家介绍了基于Bootstrap的JQuery TreeView树形控件,数据支持json字符串.list集合(MVC5)<一>, 其中的两种方式都显得有些冗余.接着上篇博客继续 ...
- android 获取包信息
private static int testPackageInfo(Context context){ int localVersionCode = 9999; try { PackageInfo ...
- OSX下Python模块安装常见问题解决
he following error occurred while trying to add or remove files in theinstallation directory: [Errno ...
- Clojure web初探
项目环境:3.2.0-52-generic #78-Ubuntu SMP Fri Jul 26 16:21:44 UTC 2013 x86_64 x86_64 x86_64 GNU/LinuxLein ...
- JAVA要死了吗?不!我来告诉你为什么!
我们看到"Java 死了吗?" 这个问题,年年都被抛出来,然而至今为止,从所有的第三方统计来看,Java 不仅活的很好,还在保持增长.虽然不断有新的语言面世,TIOBE 仍将 Ja ...
- SHOI 2009 会场预约 平衡树 STL练习
题目描述 PP大厦有一间空的礼堂,可以为企业或者单位提供会议场地.这些会议中的大多数都需要连续几天的时间(个别的可能只需要一天),不过场地只有一个,所以不同的会议的时间申请不能够冲突.也就是说,前一个 ...
- 在laravel下關於blade模板的嘗試
Blade模板 關於模板繼承和分區段 @section和@yield的實驗 ①關於@section...@show嘗試 測試1 {{--appV2test.blade.php--}} <html ...
- jQuery下通过$.browser来判断浏览器
使用方法: $.browser.['浏览器关键字'] 代码如下: $(function() { if($.browser.msie) { alert("this is msie") ...