现在根据鼠标点击的屏幕位置能够得到屏幕的坐标event.clientXevent.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.clientXevent.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.clientXevent.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跟随物体一起旋转的更多相关文章

  1. Three.js之绘制中文文字并跟随物体

    本周更新的需求是物体上显示文字信息,效果图如下: 加载字体 import { FontLoader } from 'three/examples/jsm/loaders/FontLoader.js'; ...

  2. three.js 元素跟随物体效果

    需求: 1.实现元素跟随指定物体位置进行位置变化 实现方案: 1--- Sprite 精灵 2  --- cavans 画图后创建模型贴图 3 --- CSS2DRenderer渲染方式 4 --- ...

  3. Unity3D——相机跟随物体移动

    public Transform target; public float moveSmooth=5f; Vector3 offset; void Start () { offset = transf ...

  4. unity3d简单的相机跟随及视野旋转缩放

    1.实现相机跟随主角运动 一种简单的方法是把Camera直接拖到Player下面作为Player的子物体,另一种方法是取得Camera与Player的偏移向量,并据此设置Camera位置,便能实现简单 ...

  5. SCRDet——对小物体和旋转物体更具鲁棒性的模型

    引言 明确提出了三个航拍图像领域内面对的挑战: 小物体:航拍图像经常包含很多复杂场景下的小物体. 密集:如交通工具和轮船类,在航拍图像中会很密集.这个DOTA数据集的发明者也提到在交通工具和轮船类的检 ...

  6. 在threejs中对3D物体旋转的思考

    今天在写threejs时,突然想到一个问题:一个3D物体需要旋转时,一般情况下简单的旋转我都是使用欧拉角,稍微复杂一些的情况我会把欧拉角转换成四元数进行旋转(欧拉角复杂旋转可能会产生的死锁问题),但是 ...

  7. Unity3d学习 相机的跟随

    最近在写关于相机跟随的逻辑,其实最早接触相机跟随是在Unity官网的一个叫Roll-a-ball tutorial上,其中简单的涉及了关于相机如何跟随物体的移动而移动,如下代码: using Unit ...

  8. 首个threejs项目-前端填坑指南

    第一次使用threejs到实际项目中,开始的时候心情有点小激动,毕竟是第一次嘛,然而做着做着就感受到这玩意水好深,满满的都是坑,填都填不过来.经过老板20天惨无人道的摧残,终于小有成就. 因为第一次搞 ...

  9. canvas 图片拖拽旋转之一——坐标转换translate

    引言 对canvas中绘制的图片进行旋转操作,需要使用ctx.translate变换坐标系,将图片旋转的基点设为坐标系的原点,然后ctx.rotate旋转. 这个时候,因为canvas坐标系发生了旋转 ...

随机推荐

  1. [Dynamic Programming]动态规划之背包问题

    动态规划之背包问题 例题 现有4样物品n = ['a', 'b', 'c', 'd'],重量分别为w = [2, 4, 5, 3],价值分别为v = [5, 4, 6, 2].背包最大承重c = 9. ...

  2. Java容器的常见问题

    记录Java容器中的常见概念和原理 参考: https://github.com/wangzhiwubigdata/God-Of-BigData#三Java并发容器 https://blog.csdn ...

  3. Django 缓存机制

    一 缓存介绍 在动态网站中,用户所有的请求,服务器都会去数据库中进行相应的增,删,查,改,渲染模板,执行业务逻辑,最后生成用户看到的页面. 当一个网站的用户访问量很大的时候,每一次的的后台操作,都会消 ...

  4. TensorFlow 基本变量定义,基本操作,矩阵基本操作

    使用 TensorFlow 进行基本操作的实例,这个实例主要是使用 TensorFlow 进行了加法运算. 包括使用 constant 常量进行加法运算和使用 placeholder 进行变量加法运算 ...

  5. 使用DeepWalk从图中提取特征

    目录 数据的图示 不同类型的基于图的特征 节点属性 局部结构特征 节点嵌入 DeepWalk简介 在Python中实施DeepWalk以查找相似的Wikipedia页面 数据的图示 当你想到" ...

  6. DeepMind爆出无监督表示学习模型BigBiGAN,GAN之父点赞!

    [导读]今天,DeepMind爆出一篇重磅论文,引发学术圈热烈反响:基于最强图像生成器BigGAN,打造了BigBiGAN,在无监督表示学习和图像生成方面均实现了最先进的性能!Ian Goodfell ...

  7. coding++ :JS-判断当前是否是IE浏览器,并返回时IE几?

    IEVersion(); function IEVersion() { var userAgent = navigator.userAgent; //取得浏览器的userAgent字符串 var is ...

  8. EF Core 数据变更自动审计设计

    EF Core 数据变更自动审计设计 Intro 有的时候我们需要知道每个数据表的变更记录以便做一些数据审计,数据恢复以及数据同步等之类的事情, EF 自带了对象追踪,使得我们可以很方便的做一些审计工 ...

  9. [bzoj1800]fly 飞行棋<暴力>

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1800 说实话我这几天运气不错,随便在bzoj上找题都可以找到水题,这题在代码上没有丝毫难度 ...

  10. Python第三方包之离线安装

    Python第三方包之离线安装 第一步 首先我们得从pypi上先下载要装的第三方包 https://pypi.org/ 第二步(因为下载下来的包可能需要其他包的依赖,那我们依旧要按照第一步再次下载) ...