three.js中坐标系转换以及camera的position、lookAt与up属性理解

       为了更好的理解camera的position、lookAt与up属性,文章最开始我们先来阐述three.js的坐标系转换的概念。

1.监听event的事件获得屏幕坐标

       文章的最开始首先讨论在哪里进行点击事件的监听的问题,当鼠标触发点击事件时,event会输出点击位置相对于各个参考系所产生的坐标,在此我们只讨论常用的offsetX、offsetY以及clientX、clientY。

offsetX:设置或获取鼠标点击位置相对于触发事件对象(触发事件DOM的内部不包含border)的水平(X)距离
offsetY:设置或获取鼠标点击位置相对于触发事件对象(触发事件DOM的内部不包含border)的垂直(Y)距离

clientX:设置或获取鼠标相对于浏览器可视区域的水平坐标    
clientY:设置或获取鼠标相对于浏览器可视区域的垂直坐标    

     如图(1)示,window中(clientX,clientY)都是相对于左上角坐标原点的距离,而(offsetX,offsetY)中触发事件的对象这个概念就很重要,是相对于当前DOM元素不包含border及其外部的content部分左上角原点坐标,如果在展示界面存在header,(clientX,clientY)还需要转换才能作为画布的坐标,所以推介选取(offsetX,offsetY)作为监听事件获得的坐标。

                                                       图(1)不同坐标数据展示

         如果展示模型的画布如果是整个可视页面,监听window得到的坐标(clientX,clientY)与(offsetX,offsetY)都是一致的。但往往我们只会选择一个区域进行三维模型的展示, 这时若监听对象为window,就会在画布外触发点击事件,容易产生不必要的问题。所以此时最好把监听对象设置为存放画布的DOM元素,不仅在画布外不会触发不必要的事件,并且可以直观的获得该点相对于画布的坐标。

element.addEventListener('click',()=>{})
window.addEventListener('click',()=>{})

     

2 屏幕坐标、标准化设备坐标与世界坐标的相互转换

这里我们先抛出屏幕坐标、标准化设备坐标与世界坐标的概念。

2.1 概念:

屏幕坐标:以左上角为原点,横向为x轴,纵向向下为y轴;屏幕坐标系在three.js中为canvas画布的坐标系,如图(2)示

                                                        图(2)屏幕坐标系

标准化设备坐标(NormalizedDeviceCoordinates,NDC) :标准化设备坐标是一个横纵坐标值在-1到1的一小段空间,坐标原点位于区域正中心。如图(3)示

                                                         图(3)标准化设备坐标系

世界坐标:场景坐标原点坐标系,世界坐标是物体相对场景坐标原点的位置,如图(4)示

                                                          图(4)世界坐标系

2.2 屏幕坐标系转世界坐标系

首先我们了解如何从屏幕坐标系转化为标准化设备坐标系,最后转化为世界坐标系的过程 。

step 1:

当鼠标在canvas画布上点击时,获得屏幕坐标系(Sx,Sy),将其转化为( Nx,Ny),可得

N_{x}=\frac{S_{X}}{width}*2-1

 N_{y}=-\frac{y}{height}*2+1

转化为代码就是

const x = (x / Width) * 2 - 1,

const y = - (y /Height) * 2 + 1,

step 2: 

将得到的设备坐标转化为三维向量;

const nVector = new THREE.Vector3((x / Width) * 2 - 1,- (y /Height) * 2 + 1,0.5) 

step 3: 

 three.js有封装好的方法.unporject( ),将设备坐标转为世界坐标系;

const worldVector = nVector.unprojet( camera )

 2.2世界坐标系转屏幕坐标系

        同上可得

 step1:

 将世界坐标系转化为标准坐标系

const nVector = worldVector .projet( camera )

step2:

将标准坐标系转化为屏幕坐标系,公式为

S_{x}=\frac{N_{x}+1}{2}width

S_{y}=\frac{N_{y}-1}{2}height

3 camera的position、lookAt与up属性

3.1camera的position

.position:Vectors

 表示对象局部位置的Vector3。默认值为(0, 0, 0)

       官方文档的解释很容易理解,就是相机相对于世界坐标系原点的位置,换句话说相机距离场景中心的距离。距离越近看到的物体越少越大,距离越远看到的物体越多越小。设置一个合适的位置对于观察场景内模型具有很重要的意义。

                                                          图(5)相机看向物体

3.2 .lookAt

object3D.lookAt ( vector:Vector3) :undefined
object3D.lookAt( x : Float, y : Float, z : Float ) :undefined

vector - 一个表示世界空间中位置的向量。

也可以使用世界空间坐标的位置分量。
旋转物体使其在世界空间中面朝一个点。

这一方法不支持其父级被旋转过或者被位移过的物体。

       也就是说,这个object的永远朝向 .lookAt( ) 中向量的位置,如果在创建object时使用这个属性,就会产生构建的物体总是会朝向向量的方向,图(6)示为raycaster射线射中返回的数据,借由这些数据和。lookAt()方法,我们可以完成很多有趣的功能,例如在物体表面形成数据点,或者构建垂直于当前面的线等等。

                                                           图(6)相机看向物体

       而相机的这个属性可以理解为”看向“哪里,只有保证视角中出现这个对象,我们才能通过画布看到。在渲染场景时,通常都是将相机看向场景的原点,以此来保证可视界面的完整,我们也可以把相机放置在场景中移动的物体上,设置看向某个方向,借此完成动态巡检等功能。

3.3 up

.up:Vector3

这个属性由lookAt方法所使用,例如,来决定结果的朝向。 默认值是Object3D.DefaultUp,

即( 0, 1, 0 )

       通过前面阐述的世界坐标系概念可知,这个”结果的朝向“指的是场景的坐标系的朝向,默认的朝向为Y轴向上,X轴向右,Z轴向外,那么我们设置这个值会得到什么?

a.设置Y轴向上

      换句话说,就是哪个方向是向上的,设置.up为(0,1,0),就可以得到图(7)的样式,Y轴向上,X轴向右,Z轴向外。

camera.position.set(1,30,60)

camera.lookAt(0,0,0)

camera.up = new THREE.Vector3(0,1,0) 

                                                            图(7)Y轴向上

b.设置Y轴向上

       那么,设置.up为(1,0,0),就可以得到图(8)的样式,x轴向上,X轴向坐,Z轴向外。

camera.position.set(1,30,60)

camera.lookAt(0,0,0)

camera.up = new THREE.Vector3(1,0,0) 

                                                            图(8)X轴向上

c.设置Z轴向上

         设置.up为(0,0,1)时,就可以得到图(9),由图可知Z轴向外,那么为什么Z轴没有向上?通过图(10)可以知道相机的位置在Z轴正半轴,看向Z轴的负半轴,改变.up()的值,相机的位置也是在跟随着一起移动,所以得到如图所示的结果。

camera.position.set(1,30,60)

camera.lookAt(0,0,0)

camera.up = new THREE.Vector3(1,0,0) 

                                                            图(9)Z轴向上

  • 11
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值