zoukankan      html  css  js  c++  java
  • Threejs【坐标转换】如何让annotation跟随物体一起旋转

    现在根据鼠标点击的屏幕位置能够得到屏幕的坐标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); //1
        screenCoord.x = Math.round((0.5 + vector.x / 2) * (canvas.width / window.devicePixelRatio));  //2
        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的位置

    应该就可以了

  • 相关阅读:
    为什么使用GitHub
    java学习笔记
    mysql 内置功能 存储过程 创建有参存储过程
    mysql 字符串类型 char varchar
    前端 HTML 注释
    mysql 内置功能 存储过程 删除存储过程
    前端开发 目录
    mysql 内置功能 存储过程 创建无参存储过程
    mysql 内置功能 存储过程 目录
    mysql 内置功能 存储过程介绍
  • 原文地址:https://www.cnblogs.com/smedas/p/12445316.html
Copyright © 2011-2022 走看看