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

news2025/1/27 12:32:37

       为了更好的理解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轴向上

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/407752.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用JS监听键盘按下事件

事件说明 我们将键盘按下后事件的所有属性和方法打印出来(这里以按下1为例) document.onkeydown function(event){console.log(event);} 这里面有几个需要注意的属性 key:按下按键的名称 keyCode:按下按键的键码 altKey、ctrlKey、shiftKey&#xf…

Vue项目实战——【基于 Vue3.x + Vant UI】实现一个多功能记账本(项目演示、涉及知识点、源码分享)

基于 Vue3.x Vant UI 的多功能记账本(一) 文章目录基于 Vue3.x Vant UI 的多功能记账本(一)Vue3.x 实现多功能记账本1、前言2、项目演示3、涉及知识点4、写到最后(附源码)Vue3.x 实现多功能记账本 1、前…

文件在线浏览之微软office在线预览及隐藏的坑和其他更优解决办法

一 微软也已经免费提供在线版本office预览啦 https://view.officeapps.live.com/op/view.aspx?srcURLsrc后面的URL是网上能访问到的文件地址,比如http://abc.com/file/demo.xlsx 直接访问:https://view.officeapps.live.com/op/view.aspx?srchttp:/…

js模板字符串

js模板字符串模板字符串(模板字面量)在模板字符串中插入变量在模板字符串中插入表达式模板字符串中可以换行模板字符串中可以调用函数模板字符串支持嵌套使用模板字符串(模板字面量) ES6 中引入了模板字符串,让我们省…

Vue3 + vite 创建项目

项目创建 vite的介绍 首先要想使用vite来创建一个vue项目,要把vue脚手架升级成为5.0.1版本,但是有一个很大的缺陷,就是升级过后不会再向下兼容vue2的语法创建项目的方式 脚手架升级为5.0.1版本:cnpm install vuenext 或 yarn gl…

Redux最新实践指南之Redux-Toolkit

前言 redux-toolkit是目前redux官方推荐的编写redux逻辑的方法,针对redux的创建store繁琐、样板代码太多、依赖外部库等问题进行了优化,官方总结了四个特点是简易的/有想法的/强劲的/高效的,总结来看,就是更加的方便简单了。 从官…

vue-treeselect 的基本使用

官网地址:Vue-Treeselecthttps://vue-treeselect.js.org/公司用 若依 搞了一个速成项目,若依是一个免费开源的前后端项目,感兴趣的朋友百度。 在里边接触到了一个神奇的东西 :vue-treeselect,用起来真的是一言难尽&am…

uniapp全局弹窗(APP端)

uniapp自带的提示框不符合我们的要求,需要自己写一个提示框,且全局通用。 解决思路: 使用 plus.nativeObj 来绘制窗口以及事件监听。 官方文档 1. 首先创建一个整个屏幕的控件,作为一个父容器。 此时还看不到任何东西 let screenHeight…

牛客网前端刷题(二)

还在担心面试不通过吗?给大家推荐一个超级好用的刷面试题神器:牛客网,里面涵盖了各个领域的面试题库,还有大厂真题哦! 赶快悄悄的努力起来吧,不苒在这里衷心祝愿各位大佬都能顺利通过面试。 面试专栏分享,感觉有用的小伙伴可以点个订阅,不定时更新相关面试题:面试专栏…

微信小程序之开发遇到 does not have a method “xxxx“ to handle event “tap“ 问题的解决方案【已解决】

今天在开发一个小功能,copy了之前写的代码,但是在实现功能时,出现了如下问题: 先在这简单总结一下解决方案: 在调用方法时,在" "中前后多加了空格;在 js 中没有定义该方法&#xff1…

纯前端导出表格

前端 excel 表格导出 我们习惯了后端去处理表格,直接接口返回 ,那前端如何轻松的导出表格呢? 文章目录前端 excel 表格导出Ⅰ. 通过 js-xlsx ⭐⭐⭐⭐⭐安装① vue2 中使用② vue3 中使用③ react 中使用Ⅲ. 通过 vue-json-excel ⭐⭐安装使…

SpringBoot--Filter过滤器(一)

一.了解过滤器Filter 过滤器: Filter, 是 Servlet 技术中最实用的技术。过滤器是处于客户端和服务器之间的一个过滤网,可以过滤掉一些不符合要求的请求常见场景: Session 校验判断用户权限不符合设定条件,则会被重定向特殊的地址或者设定的响应过滤敏感词汇设置编…

一天撸一个财务APP系统【安卓端+前端+后端】

昨天有个粉丝朋友也想学开发Web和小程序、安卓,问可以在大学学会吗? 在学校学到的东西真的有限: 在很多的高校,有一些教授是学院派的,他们没有做过多少开发工作,上课就是照本宣科,讲的知识点都…

Vue打包优化篇-CDN加速

优化原因 在没有使用cdn加速之前打包后数据如下,可以看出element-ui、vue、vuex、vue-router这些依赖都打进chunk-vendors.js中导致体积很大,假设再来很多依赖项是不是更大,同时也会影响单页面应用首屏加载速度,所以这里采用一种打…

Vue的组件化编程

非单文件组件 注册局部组件 此时上面书写的组件都是局部组件,每一个vue实例要想使用上面的组件时都需要在components中进行注册才可以使用,此时如果再创建一个Vue实例vms,这个实例不在components中注册就直接使用组件会产生什么变化: 此时控制台报错 ‘是否正确注册了组件&a…

function 函数

一、函数的基本注意事项 function函数的名字也是一个标识符,通过关键字function申明一个函数 function 函数名(){ 代码块 } 二、函数基本用法 1、形参与实参 1、形参与实参可以有无数个,实参按照顺序赋值给形参; 2、实参个数不一定要与实…

web前端面试高频考点——Vue原理(理解MVVM模型、深度/监听data变化、监听数组变化、深入了解虚拟DOM)

系列文章目录 内容参考链接Vue基本使用Vue的基本使用(一文掌握Vue最基础的知识点)Vue通信和高级特性Vue组件间的通信及高级特性(多种组件间的通信、自定义v-model、nextTick、插槽)Vue高级特性Vue的高级特性(动态组件…

axios发post请求,后端接收不到参数的原因及解决

做分页数据时,使用vue3 axios发post请求,后端服务调用成功但数据没有根据参数动态变化,换为js ajax也是同样错误。 后来是后端没有接收到参数。 网上看了资料,原因: 使⽤axios请求数据时,我们的 …

Module Federation在vue3中使用vue2的组件

前言: 备注:本文基于对webpack Module Federation有一定了解的情况下 一般情况下使用模块联邦都是会使用相同的版本,如Vue2的组件时在Vue2中使用,但我为什么会在Vue3项目中去使用Vue2的组件呢,其实是因为历史原因。好…

点击《el-table》让选中的行变色,亲测实用

前期回顾 Vue项目实战 —— 哔哩哔哩移动端开发_0.活在风浪里的博客-CSDN博客撑着下班前半小时我用vue写《哔哩哔哩 项目》移动端、新手还在哭、老鸟一直在笑。。。技术选型Vue2,技术栈有axios、Vh等,下班过来敲哈哈https://blog.csdn.net/m0_5790…