ready
论坛版主
论坛版主
  • UID24
  • 粉丝0
  • 关注0
  • 发帖数433
  • 社区居民
  • 忠实会员
  • 原创写手
阅读:671回复:1

Three.js raycaster 填坑

楼主#
更多 发布于:2024-07-07 12:05
Three.js中raycaster是射线,用于拾取物体的。

通过 THREE.Raycaster 实现模型选中与信息显示。


这是官方例子:



var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
 
function onMouseMove( event ) {
 
        mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
        mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
 
}
 
function render() {
        raycaster.setFromCamera( mouse, camera );
        var intersects = raycaster.intersectObjects( scene.children );
 
        for ( var i = 0; i < intersects.length; i++ ) {
 
                intersects[ i ].object.material.color.set( 0xff0000 );
 
        }
 
        renderer.render( scene, camera );
 
}
 
window.addEventListener( 'mousemove', onMouseMove, false );
 
window.requestAnimationFrame(render);




简单讲解下原理:

webgl把中心点设置为0,然后把世界坐标分成高(-1,1)之间,宽也如此,所以首先把鼠标点击的位置转换成(-1,1)之间,然后从相机所在位置到鼠标点击的位置的连线画一条射线,射线穿过的物体就会被拾取。
重点是: 很多教程里,计算mouse.x和mouse.y的时候都是认为canvas占据整个屏幕计算的,所以用的window.innerWidth和window.innerHeight。但是:

mouse.x和mouse.y是相对绘制的canvas计算,也就是说canvas的中心是(0,0),canvas的高和宽被分成(-1,1),所以如果你的canvas不是整个屏幕,用上述代码是无法正确拾取物体的。



下面直接上修改后的代码:

<canvas width="600" height="600" id="canvas-dom-2">您的浏览器不支持canvas!</canvas>

var mainCanvas = document.getElementById("canvas-dom-2");            


            renderer = new THREE.WebGLRenderer({

                canvas: mainCanvas,

                antialias:true, //设置抗锯齿

                alpha:true, //背景透明

            });

            renderer.setClearColor(0x000000,0.0); //设置渲染器背景颜色  

            renderer.setSize(mainCanvas.offsetWidth,mainCanvas.offsetHeight);

mainCanvas.addEventListener( 'click', onDocumentClick, false );


————————————————


        function onDocumentClick(event){
            event.preventDefault();
            //console.log(mainCanvas.offsetWidth+"+"+mainCanvas.offsetHeight);
            mouse.x = ( (event.clientX - mainCanvas.getBoundingClientRect().left) / mainCanvas.offsetWidth ) * 2 - 1;
            mouse.y = - ( (event.clientY - mainCanvas.getBoundingClientRect().top) / mainCanvas.offsetHeight ) * 2 + 1;
 
            raycaster.setFromCamera( mouse, camera );
            var intersects = raycaster.intersectObjects( object );
 
            for ( var i = 0; i < intersects.length; i++ ) {
                console.log(intersects[ i ].object.userData.uid);
 
            }
 
        }

注意上面计算mouse的x和y的代码




https://blog.csdn.net/u013090676/article/details/77188088
ready
论坛版主
论坛版主
  • UID24
  • 粉丝0
  • 关注0
  • 发帖数433
  • 社区居民
  • 忠实会员
  • 原创写手
沙发#
发布于:2024-07-07 12:52
首先,解释一下三种坐标系的概念:场景坐标系(世界坐标系)、屏幕坐标系、视点坐标系。
场景坐标
通过three.js构建出来的场景,都具有一个固定不变的坐标系(无论相机的位置在哪),并且放置的任何物体都要以这个坐标系来确定自己的位置,也就是(0,0, 0)坐标。例如我们创建一个场景并添加箭头辅助。
————————————————


屏幕坐标
在显示屏上的坐标就是屏幕坐标系。
如下图所示,其中的clientXclientY的最值由,window.innerWidth,window.innerHeight决定。


视点坐标
视点坐标系就是以相机的中心点为原点,但是相机的位置,也是根据世界坐标系来偏移的,webGL会将世界坐标先变换到视点坐标,然后进行裁剪,只有在视线范围(视见体)之内的场景才会进入下一阶段的计算




射线检测

若想获取鼠标点击的物体,name就需要把屏幕坐标系转换为three.js中的三维坐标系。
three.js提供了一个类THREE.Raycaster可以用来解决这个问题。
看个示例图



THREE.Raycaster对象从屏幕上的点击位置向场景中发射一束光线。



// 计算出鼠标经过的3d空间中的对象

Raycaster( origin, direction, near, far ) { }



origin — 射线的起点向量。
direction — 射线的方向向量,应该归一化。
near — 所有返回的结果应该比 near 远。Near不能为负,默认值为0。
far — 所有返回的结果应该比 far 近。Far 不能小于 near,默认值为无穷大。
&


……


https://blog.csdn.net/ithanmang/article/details/80897888

游客


返回顶部