Threejs【坐标转换】如何让annotation跟随物体一起旋转
现在根据鼠标点击的屏幕位置能够得到屏幕的坐标event.clientX和event.clientY,然后我的annotation就初始化在这个屏幕坐标的位置,那么如何绑定annotation和三维物体,使得物体旋转的时候可以让annotation跟随物体一起旋转呢?
问题一:我知道的一种方法如下:
/* 修改注解屏幕位置函数体 实时更新,实际是三维坐标向屏幕坐标的映射*/
function updateScreenPosition() {
var canvas = renderer.domElement; var vector = new THREE.Vector3(50, 0, 250); // 控制annotation的位置
vector.project(camera);
vector.x = Math.round((0.5 + vector.x / 2) * (canvas.width / window.devicePixelRatio)); // 控制annotation跟随物体一起旋转
vector.y = Math.round((0.5 - vector.y / 2) * (canvas.height / window.devicePixelRatio)); annotation.style.top = vector.y + "px";
annotation.style.left = vector.x + "px";
annotation.style.opacity = spriteBehindObject ? 0.25 : 1;
}
上面的方法可以控制annotation和物体一起旋转,但是annotation的位置确实预先设定的:
var vector = new THREE.Vector3(50, 0, 250); // 控制annotation的位置
对于上面这行代码,Vector3是个什么坐标系下的向量呢?当我在修改Vector3中的三个坐标的时候,发现它并不是控制annotation的位置的向量,比如我把鼠标点击位置的参数传递过来,然后触发鼠标点击事件,然后发现鼠标点击的位置并不是annotation的位置。如何把它和鼠标点击的屏幕坐标挂钩呢?
问题二:如果不预先设定好这个Vector3 而是使用鼠标,而是直接传递event.clientX和event.clientY
function updateAnnosPosition(){
var canvas = renderer.domElement;
var vector = new THREE.Vector3(clientX,clientY,-1);
vector.project(camera);
//这个位置的写法有问题
annos.style.left = clientX + "px";
annos.style.top = clientY + "px";
annos.style.opacity = spriteBehindObject ? 0.25 : 1;
}
这样是可以在鼠标点击位置触发annotation的,但是annotation却不跟随物体旋转。
网上查了一下,大概是要进行屏幕坐标与三维坐标之间的转换:
_mouse.x = ( event.clientX / _domElement.width ) * 2 - 1;
_mouse.y = - ( event.clientY / _domElement.height ) * 2 + 1;
但是还是不行,求教该如何处理。
(1)Vector3是个什么坐标系下的向量呢?
Vector3是 three.js 定义的三维空间坐标系里的向量
(2)如何把它和鼠标点击的屏幕坐标挂钩呢?
这个问题本质是问:如何将three.js 三维坐标转换成屏幕二维坐标
其实updateScreenPosition()函数就是将三维坐标转换成屏幕坐标的过程,我们可以改一下这个函数,使之更通用:
/**
* 将three.js三维坐标转换成屏幕上的二维坐标
* @param THREE.Vector3 vector three.js三维坐标
* @return {x:int,y:int} 屏幕坐标
*/
function transToScreenCoord(vector) {
var screenCoord = {};
vector.project(camera); //
screenCoord.x = Math.round((0.5 + vector.x / 2) * (canvas.width / window.devicePixelRatio)); //
screenCoord.y = Math.round((0.5 - vector.y / 2) * (canvas.height / window.devicePixelRatio));
return screenCoord;
}
有了这个函数,就可以把任意three.js三维坐标转换成屏幕坐标。也就是实现了3维坐标和屏幕坐标挂钩
接下来解释一下这个转换的过程:vector.project(camera) 这句的意思是,将一个三维坐标,投影到相机平面上,使之变成一个二维坐标。需要注意的是,投影得到的结果是一个标准向量(或者叫单位向量),其值是限定在[-1,1]范围内的。并且,这个向量是定义在以屏幕中心为原点的坐标系里的,这个坐标系和屏幕坐标系的关系,就像下图一样:
假如经过投影之后的点就是上图中的点A(0.3,0.5),屏幕坐标系是sx-s0-sy,相机平面坐标系是tx-t0-ty,坐标系的各项参数已经标在图上,试着求A点在屏幕坐标系中的坐标。你求一遍的话,就会理解上面这个函数的意思。
(3)如果不预先设定好这个Vector3 而是使用鼠标,而是直接传递event.clientX和event.clientY,该怎么处理?
处理方法就是将这个屏幕二维坐标转three.js三维坐标,按照下面这个方法来处理:
var vector = new THREE.Vector3();
vector.x = ( event.clientX / _domElement.width ) * 2 - 1;
vector.y = - ( event.clientY / _domElement.height ) * 2 + 1;
把上面这段替换掉updateScreenPosition()函数中的:
var vector = new THREE.Vector3(50, 0, 250); // 控制annotation的位置
应该就可以了
Threejs【坐标转换】如何让annotation跟随物体一起旋转的更多相关文章
- Three.js之绘制中文文字并跟随物体
本周更新的需求是物体上显示文字信息,效果图如下: 加载字体 import { FontLoader } from 'three/examples/jsm/loaders/FontLoader.js'; ...
- three.js 元素跟随物体效果
需求: 1.实现元素跟随指定物体位置进行位置变化 实现方案: 1--- Sprite 精灵 2 --- cavans 画图后创建模型贴图 3 --- CSS2DRenderer渲染方式 4 --- ...
- Unity3D——相机跟随物体移动
public Transform target; public float moveSmooth=5f; Vector3 offset; void Start () { offset = transf ...
- unity3d简单的相机跟随及视野旋转缩放
1.实现相机跟随主角运动 一种简单的方法是把Camera直接拖到Player下面作为Player的子物体,另一种方法是取得Camera与Player的偏移向量,并据此设置Camera位置,便能实现简单 ...
- SCRDet——对小物体和旋转物体更具鲁棒性的模型
引言 明确提出了三个航拍图像领域内面对的挑战: 小物体:航拍图像经常包含很多复杂场景下的小物体. 密集:如交通工具和轮船类,在航拍图像中会很密集.这个DOTA数据集的发明者也提到在交通工具和轮船类的检 ...
- 在threejs中对3D物体旋转的思考
今天在写threejs时,突然想到一个问题:一个3D物体需要旋转时,一般情况下简单的旋转我都是使用欧拉角,稍微复杂一些的情况我会把欧拉角转换成四元数进行旋转(欧拉角复杂旋转可能会产生的死锁问题),但是 ...
- Unity3d学习 相机的跟随
最近在写关于相机跟随的逻辑,其实最早接触相机跟随是在Unity官网的一个叫Roll-a-ball tutorial上,其中简单的涉及了关于相机如何跟随物体的移动而移动,如下代码: using Unit ...
- 首个threejs项目-前端填坑指南
第一次使用threejs到实际项目中,开始的时候心情有点小激动,毕竟是第一次嘛,然而做着做着就感受到这玩意水好深,满满的都是坑,填都填不过来.经过老板20天惨无人道的摧残,终于小有成就. 因为第一次搞 ...
- canvas 图片拖拽旋转之一——坐标转换translate
引言 对canvas中绘制的图片进行旋转操作,需要使用ctx.translate变换坐标系,将图片旋转的基点设为坐标系的原点,然后ctx.rotate旋转. 这个时候,因为canvas坐标系发生了旋转 ...
随机推荐
- Android AlertDialog 各种弹框代码
1.消息框 btn01.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ...
- Flutter 使用阿里巴巴icon库
在Flutter默认创建的项目中可以使用系统Material图标,在pubspec.yaml文件中使用图标设置如下: flutter: uses-material-design: true 系统图标如 ...
- Spring优雅整合Redis缓存
“小明,多系统的session共享,怎么处理?”“Redis缓存啊!” “小明,我想实现一个简单的消息队列?”“Redis缓存啊!” “小明,分布式锁这玩意有什么方案?”“Redis缓存啊!” “小明 ...
- Contest 157
2019-10-06 12:15:28 总体感受:总体难度一般,dfs和dp题花了点时间,最后一题dp有思路,但是实现上不够好. 注意点:首先是hard问题的覆盖度依然是很大的问题,其次是要注意审题. ...
- Mysql中的三类锁,你知道吗?
导读 正所谓有人(锁)的地方就有江湖(事务),人在江湖飘,怎能一无所知? 今天来细说一下Mysql中的三类锁,分别是全局锁.表级锁.行级锁. 文章首发于作者公众号[码猿技术专栏],原创不易,喜欢的点个 ...
- 本地缓存Ehcache
1,什么是Ehcache Ehcache是纯java的开源缓存框架,具有快速.精干等特点,是Hibernate中默认的CacheProvider.它主要面向通用缓存.Java EE和轻量级容器, ...
- springboot系列(三)配置文件详解
目录 properties 文件 1.语法 2.优先级 3.自定义数据配置 4.获取自定义数据配置 1.通过prefix获取 yml文件 1.语法 2.优先级 3.自定义数据配置. 4.获取自定义数据 ...
- Docker容器入门-基本命令的使用
目前容器技术使用相当广泛 不会或者没有使用过容器感觉都不像是个搞技术的 所以,我也就docker相关内容做一个整理 只有不断的学习,才能保持自己的竞争力 什么是容器? 容器是一种轻量级.可移植.自包含 ...
- Android进阶之AIDL的使用详解
原文首发于微信公众号:jzman-blog,欢迎关注交流! AIDL(Android 接口定义语言),可以使用它定义客户端与服务端进程间通信(IPC)的编程接口,在 Android 中,进程之间无法共 ...
- ftp 无法显示远程文件夹
翻阅了网上前辈们的答案,都未能解决,所以就研究了一下 不需要防火墙的情况,关闭防火墙即可 下面使用的iptables防火墙验证的,其他的请自行验证 研究了好久,发现ftp使用端口波动很大,大概在300 ...