【问题标题】:ray doesn't reach JSONray 没有到达 JSON
【发布时间】:2025-12-20 17:10:07
【问题描述】:

我正在尝试通过鼠标单击事件捕获 JSON 对象。我使用射线来识别物体,但由于某种原因,物体并不总是被识别出来。我怀疑这与我移动相机有关,因为当我在物体附近单击时,我被识别出来了。

你能帮我弄清楚如何根据相机移动正确设置光线吗?

代码如下:

这是鼠标按下事件的一部分 *

    document.addEventListener("mousemove", onDocumentMouseMove, false);
    document.addEventListener("mouseup", onDocumentMouseUp, false);
    document.addEventListener("mouseout", onDocumentMouseOut, false);
    mouseXOnMouseDown = event.clientX - windowHalfX;
    targetRotationOnMouseDown = targetRotation;
    var ray, intersections;
    _vector.set((event.clientX / window.innerWidth) * 2 - 1, -(event.clientY / window.innerHeight) * 2 + 1, 0);
    projector.unprojectVector(_vector, camera);
    ray = new THREE.Ray(camera.position, _vector.subSelf(camera.position).normalize());
    intersections = ray.intersectObjects(furniture);

    if (intersections.length > 0) {
        selected_block = intersections[0].object;
        _vector.set(0, 0, 0);
        selected_block.setAngularFactor(_vector);
        selected_block.setAngularVelocity(_vector);
        selected_block.setLinearFactor(_vector);
        selected_block.setLinearVelocity(_vector);
        mouse_position.copy(intersections[0].point);
        block_offset.sub(selected_block.position, mouse_position);
        intersect_plane.position.y = mouse_position.y;
    }

}

这是相机移动的一部分*

camera.position.x = (Math.cos(timer) * 10);
camera.position.z = (Math.sin(timer) * 10);
camera.lookAt(scene.position); 

【问题讨论】:

    标签: webgl three.js


    【解决方案1】:

    嗯,如果没有看到您的程序实际运行方式的某种演示,很难说您的问题可能是什么。我建议看看我今天一直在做的演示。我处理我的相机、控件和光线。我也在使用 JSON。

    首先您可以查看我的演示:here,了解它在做什么,您的描述听起来很相似。如果你能理解我的代码,你应该能够适应它。
    --如果您想直接链接到源代码:main.js

    我还有另一个你可能会觉得有用的地方,我使用光线和鼠标碰撞到 spin a cube
    --源码:main.js

    最后,我将在第一个演示中发布我的鼠标事件的内容以及我如何使用轨迹球相机处理它,希望其中的一些内容能够引导您找到解决方案:

    /** Event fired when the mouse button is pressed down */
    function onDocumentMouseDown(event) {
        event.preventDefault();
    
        /** Calculate mouse position and project vector through camera and mouse3D */
        mouse3D.x = mouse2D.x = (event.clientX / window.innerWidth) * 2 - 1;
        mouse3D.y = mouse2D.y = -(event.clientY / window.innerHeight) * 2 + 1;
        mouse3D.z = 0.5;
        projector.unprojectVector(mouse3D, camera);
    
        var ray = new THREE.Ray(camera.position, mouse3D.subSelf(camera.position).normalize());
    
        var intersects = ray.intersectObject(maskMesh);
    
        if (intersects.length > 0) {
            SELECTED = intersects[0].object;
            var intersects = ray.intersectObject(plane);
            offset.copy(intersects[0].point).subSelf(plane.position);
            killControls = true;
        }
        else if (controls.enabled == false)
            controls.enabled = true;
    }
    
    /** This event handler is only fired after the mouse down event and
        before the mouse up event and only when the mouse moves */
    function onDocumentMouseMove(event) {
        event.preventDefault();
    
        /** Calculate mouse position and project through camera and mouse3D */
        mouse3D.x = mouse2D.x = (event.clientX / window.innerWidth) * 2 - 1;
        mouse3D.y = mouse2D.y = -(event.clientY / window.innerHeight) * 2 + 1;
        mouse3D.z = 0.5;
        projector.unprojectVector(mouse3D, camera);
    
        var ray = new THREE.Ray(camera.position, mouse3D.subSelf(camera.position).normalize());
    
        if (SELECTED) {
            var intersects = ray.intersectObject(plane);
            SELECTED.position.copy(intersects[0].point.subSelf(offset));
            killControls = true;
            return;
        }
    
        var intersects = ray.intersectObject(maskMesh);
    
        if (intersects.length > 0) {
            if (INTERSECTED != intersects[0].object) {
                INTERSECTED = intersects[0].object;
                INTERSECTED.currentHex = INTERSECTED.material.color.getHex();
                plane.position.copy(INTERSECTED.position);
            }
        }
        else {
            INTERSECTED = null;
        }
    }
    
    /** Removes event listeners when the mouse button is let go */
    function onDocumentMouseUp(event) {
        event.preventDefault();
        if (INTERSECTED) {
            plane.position.copy(INTERSECTED.position);
            SELECTED = null;
            killControls = false;
        }
    
    }
    
    /** Removes event listeners if the mouse runs off the renderer */
    function onDocumentMouseOut(event) {
        event.preventDefault();
        if (INTERSECTED) {
            plane.position.copy(INTERSECTED.position);
            SELECTED = null;
        }
    }
    

    为了获得我想要的第一个演示中显示的预期效果,我必须将其添加到我的动画循环中,以便使用 killControls 标志根据鼠标有选择地打开和关闭轨迹球相机控件碰撞:

    if (!killControls) controls.update(delta);
    else controls.enabled = false;
    

    【讨论】: