美文网首页
三维空间中的绝对定位

三维空间中的绝对定位

作者: 不决书 | 来源:发表于2019-10-14 20:55 被阅读0次

在三维空间中项目模拟一个立体的球在屏幕中从左移动到右边,然后在从屏幕的左边出来,继续重复移动,类似与二维动画的跑马灯,那么问题就来了,如何将球定位到屏幕的最左边呢?最初我使用网上搜索的计算视锥的高和宽来控制,具体代码如下:

通过视锥高宽计算

        
         let frustumHeight = 2.0 * distance * Math.tan(camera.fov * 0.5 * THREE.Math.DEG2RAD);
        let frustumWidth = frustumHeight * camera.aspect;
    
        let tempV = item.applyMatrix4(camera.matrixWorldInverse).applyMatrix4(camera.projectionMatrix);
        
        if(tempV.x>1){
            console.log('右边越界');
            //强制移动到最左边
           movingCube.position.x = -frustumWidth - movingCube.userData.radius;
        }

        if(tempV.x<-1){
            console.log('左边越界')
          //todo
        }

        if(tempV.y>1){
            console.log('上边越界')
          //todo
        }

        if(tempV.y<-1){
            console.log('下边边越界')
          //todo
        }   

发现使用这种方面,只有当相机位置在【0,0,x】,x>0的位置上,计算的结果才是正确的,所以放弃这种算法

于是考虑既然整个投影是在视锥体中进行的,那么我只要计算,物体与视锥体的各个面的距离,然后更改物体的x,y值不就可了吗?

通过视锥体

     let frustum = new THREE.Frustum();
        frustum.setFromMatrix(new THREE.Matrix4().multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse ));
/**
*  根据法线推断
*  frustum.planes[0]  右侧的面
*  frustum.planes[1]  左侧的面
*  frustum.planes[2]  下方的面
*  frustum.planes[3]  上方的面
*  frustum.planes[4]   远裁剪面
*  frustum.planes[5]   近裁剪面
*/
//几点物体与左侧面的距离
let dir = frustum.planes[4].normal
let angle = Math.PI - frustum.planes[1].normal.angleTo(dir);
    //点到左侧面的距离
    let p2p = frustum.planes[1].distanceToPoint(movingCube.position);
    //平行与近裁面的距离
    let span = p2p / Math.cos(angle);
     sphere.position.y = span * 0.5;

这种方式的结果,与第一中结果一样,还是在X,Y方向上更改相机位置,计算的结果就不对了

[图片上传失败...(image-2cf941-1571057699827)]

最后使用屏幕坐标转化为三维坐标的方式实现,这次很稳定,不管相机和中姿态都能很好的将小球放到屏幕的任何位置,具体实现如下:

射线 与屏幕坐标到三维空间转化

    var mouse = new THREE.Vector2();
    let raycaster = new THREE.Raycaster();
    
    //相机lookAt的反方向
   let dir = camera.getWorldDirection().multiplyScalar(-1);

//定义一个面,同近裁面平行的面,深度值(z)同球的深度中相同
var plane = new THREE.Plane(dir, -10);
renderer.domElement.addEventListener('mousemove', onPointerMove, { passive: false });

function onPointerMove(event) {
  mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
  mouse.y = - (event.clientY / window.innerHeight) * 2 + 1;
  raycaster.setFromCamera(mouse, camera);

  var intersects = new THREE.Vector3();
  raycaster.ray.intersectPlane(plane, intersects);

  // console.log(raycaster.ray);
  console.log("pos=====>", mouse, intersects);
//碰撞点就是三维中的位置   
  sphere.position.copy(intersects);
  
/***** 测试结果都是正确的   ******************************************************  
//最左边
//onPointerMove({ clientX: 0, clientY: window.innerHeight * 0.5 })

//最右边
//onPointerMove({ clientX: window.innerWidth, clientY: window.innerHeight * 0.5 })

//最上边
//onPointerMove({ clientX: window.innerWidth*0.5, clientY: 0 })

//最下边
//onPointerMove({ clientX:window.innerWidth*0.5, clientY: window.innerHeight  })

}

前两种方式没有实现,高手支招,🙏

相关文章

  • 三维空间中的绝对定位

    在三维空间中项目模拟一个立体的球在屏幕中从左移动到右边,然后在从屏幕的左边出来,继续重复移动,类似与二维动画的跑马...

  • 绝对定位、相对定位与固定定位

    绝对定位如果想为元素设置层模型中的绝对定位,需要设置position:absolute(表示绝对定位),这条语句的...

  • day06

    一.CSS中的定位 1.1相对定位(relative) 相对定位就是元素在页面上正常的位置 1.2绝对定位 绝对定...

  • 前端面试记录

    1.css盒子模型中的绝对定位和相对定位的区别? absolute 绝对定位是相当于父元素的定位; fixed 绝...

  • 前端开发之绝对定位的疑问

      众所周知,css中的绝对定位,是相对于最近的已定位父元素的,父元素可以是相对定位、绝对定位或固定定位  那么,...

  • 关于CSS定位

    在CSS中关于定位的内容是:position:relative(相对定位)absolute(绝对定位) ...

  • 绝对定位相关注意点

    绝对定位注意点: 绝对定位的元素是脱离标准流的, 不会占用标准流中的位置 由于绝对定位的元素是脱离标准流的, 所以...

  • 绝对定位

    相对定位和绝对定位的区别 相对定位是“相对于”元素在文档中的初始位置,而绝对定位是“相对于”最近的已定位祖先元素,...

  • CSS中的定位绝对定位和相对定位

    1、relative相对定位会在标准流当中占位置;2、absolute绝对定位不会在标准流当中占位置;3、绝对定位...

  • CSS定位学习笔记(转)

    1.层模型--绝对定位(absolute) 如果想为元素设置层模型中的绝对定位,需要设置position:abso...

网友评论

      本文标题:三维空间中的绝对定位

      本文链接:https://www.haomeiwen.com/subject/qbssuctx.html