从鼠标位置关闭Three.js Raycast

时间:2014-06-04 10:38:13

标签: javascript jquery html5 three.js

我目前正在使用一些jQuery在three.js中构建一个应用程序。我目前正在进行光线投射,并在光线投射点击的位置放置一个助手。我或多或少地想要实现 this

我已经设法实现了这个目标,但是在移动物体的坐标并将相机移动到新位置时,我的光线投影或者至少是帮助器是关闭的。它看起来像大约30像素,但取决于您从 here

中看到的更改相机角度

以下是帮助器的代码和光线投射的onMouseMove事件。

// RAYCAST HELPER
            var geometry = new THREE.CylinderGeometry( 0, 5, 15, 3 ); // radius at top, radius at bottom, height, segments
            //geometry.applyMatrix( new THREE.Matrix4().makeTranslation( -50, 0, 0 ) );
            geometry.applyMatrix( new THREE.Matrix4().makeRotationX( Math.PI / 2 ) );
            helper = new THREE.Mesh( geometry, new THREE.MeshLambertMaterial({ color: 0xEB1515, ambient: 0xEB1515, wireframe: false }) );
            scene.add( helper );
            rays = true;

    function onMouseMove( event ) {
                    //console.log("Mouse moved");
                    $( document ).ready(function() {
                    if ( rays == true ) {

                        cX = event.clientX - $( "#info" ).width()
                        cY = event.clientY - $( "#topbar" ).height()

                        mouseVector.x = 2 * ( cX / canvaswidth ) - 1;
                        mouseVector.y = 1 - 2 * ( cY / canvasheight );
                        mouseVector.z = 1;

                        var raycaster = projector.pickingRay( mouseVector.clone(), camera );

                        for (var i = 0; i < buildingsroofs.length; i++) {
                            var intersects = raycaster.intersectObject( buildingsroofs[i]);

                            // Toggle rotation bool for meshes that we clicked
                            if ( intersects.length > 0 ) {
                                console.log("Intersection");
                                helper.position.set( 0, 0, 0 );
                                helper.lookAt( intersects[ 0 ].face.normal );
                                helper.position.copy(intersects[0].point);
                            } 
                        }
                    } //End of overarching if loop
                }) 
            } //End of onMouse function

有趣的是,我已经让它工作here但这些对象的坐标与我所追求的坐标不一致。您还可以看到我正在调整顶部div和侧面div的高度,因此这似乎不像我原先想象的那样。

5 个答案:

答案 0 :(得分:7)

正如其他一切正确一样,与您的WebGL相比,您的mouseVector xy值(即clientXclientY)很可能已关闭canvas(例如,你可能会从画布以外的某些元素中获取这些元素。

检查此问题的最简单方法是将鼠标放在画布的左上角(应为(0, 0)并在点击时注销鼠标位置以查看您的值是否已关闭。请将其应用于在右下角,检查你的画布宽度和高度。我用这种方式解决了类似的问题。在我的情况下,(cx, cy)(-10, -10),这足以导致光线投射中的实质性错误。

答案 1 :(得分:3)

奇怪的是,在将透视摄像机附近的参数从0.1更改为1

时,问题似乎已自行解决
camera = new THREE.PerspectiveCamera(45, canvaswidth / canvasheight , 0.1, 10000 );

要:

camera = new THREE.PerspectiveCamera(45, canvaswidth / canvasheight , 1, 10000 ); 

我仍然不能100%确定为何解决这个问题,但似乎有效。

编辑:将FOV从45更改为60可消除更改近摄像机参数后仍然出现的光线投影中的轻微失真。

答案 2 :(得分:0)

如果使用的是ClientX和ClientY,请使用event.OffsetX和event.OffsetY。

答案 3 :(得分:0)

对此有很多困难,并且仍然不确定我为什么会这样做,但是x和y的这种计算对我有用。

let canvas = document.querySelector('canvas');

let x = (event.offsetX / canvas.clientWidth) * 2 - 1;
let y = -(event.offsetY / canvas.clientHeight) * 2 + 1;

答案 4 :(得分:0)

因为我没有使用全屏分辨率作为WebGL画布的大小,所以我需要进行另一种计算以减去窗口和画布之间的距离,以定义鼠标实际悬停的位置。 >

function onDocumentMouseMove( event ) {
    mouseVector.x = (event.offsetX / (window.innerWidth - 240)) * 2 - 1;
    mouseVector.y = -(event.offsetY / (window.innerHeight - 100)) * 2 + 1;
}
// when the mouse moves, call the given function
document.addEventListener( 'mousemove', onDocumentMouseMove, false );

为画布大小正确计算鼠标坐标后,其中的对象会更准确地做出反应。 (此解决方案不操纵相机,只返回鼠标坐标。)

希望这会有所帮助。