当相机旋转时更新 OrbitControls 旋转

发布于 2025-01-14 19:04:50 字数 1190 浏览 3 评论 0原文

我正在使用 @react- Three/Fiber,并且正在实现第一人称控件(WASD 和光标键),并添加 OrbitControls 来导航场景。我几乎在克隆 PointerLockControls 并且我已经让它适用于 WASD 控件(更新 OrbitControls 的 target 向量,作为引用传递):

const moveForward = (distance) => {
    vec.setFromMatrixColumn(camera.matrix, 0)
    vec.crossVectors(camera.up, vec)
    camera.position.addScaledVector(vec, distance)
    orbitControls.current.target.addScaledVector(vec, distance)
}
const moveRight = (distance) => {
    vec.setFromMatrixColumn(camera.matrix, 0)
    camera.position.addScaledVector(vec, distance)
    orbitControls.current.target.addScaledVector(vec, distance)
}

但是,我不太清楚确定如何在相机旋转时更新目标。以下是我如何旋转相机及其在没有 OrbitControls 的情况下正常工作的方法:

const euler = new THREE.Euler(0, 0, 0, 'YXZ' );
euler.setFromQuaternion(camera.quaternion)
euler.y -= 0.25 * radians;
camera.quaternion.setFromEuler(euler)

此处预览:https ://codesandbox.io/s/wasd-with-orbit-9edup7

I'm using @react-three/fiber and I'm implementing first person controls (WASD & cursor keys) with addition of OrbitControls to navigate a scene. I'm pretty much cloning PointerLockControls and I've got it working for the WASD controls as such (updating the target vector of the OrbitControls, passed as ref):

const moveForward = (distance) => {
    vec.setFromMatrixColumn(camera.matrix, 0)
    vec.crossVectors(camera.up, vec)
    camera.position.addScaledVector(vec, distance)
    orbitControls.current.target.addScaledVector(vec, distance)
}
const moveRight = (distance) => {
    vec.setFromMatrixColumn(camera.matrix, 0)
    camera.position.addScaledVector(vec, distance)
    orbitControls.current.target.addScaledVector(vec, distance)
}

However, I'm not quite sure how to go about updating the target when the camera is rotated. Here's how I'm rotating the camera and its working just fine without OrbitControls:

const euler = new THREE.Euler(0, 0, 0, 'YXZ' );
euler.setFromQuaternion(camera.quaternion)
euler.y -= 0.25 * radians;
camera.quaternion.setFromEuler(euler)

Preview here: https://codesandbox.io/s/wasd-with-orbit-9edup7

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

悟红尘 2025-01-21 19:04:50

好的,您可以在这里看到工作版本: https://yvod70.csb.app/

非常简单,将相机连接到播放器/盒子上,然后移动所述对象而不是相机。作为玩家子级的相机将相对于玩家平移和旋转。

为此,第一步是获取对网格的引用:


const scene = () => {
    const mesh = useRef();

    return (
        <Canvas>
            <mesh
              ref={mesh}
            >
                <boxBufferGeometry args={[1, 1, 1]} />
                <meshBasicMaterial wireframe color={"green"} />
            </mesh>
            <Controls mesh={mesh} />
        </Canvas>
    );
}

设置完毕后,我们只需将网格引用传递给我们想要的任何 React 组件并使用它即可。在我们的例子中,它是更换相机以进行移动并将相机连接到盒子上。可以在 Controls 组件中像这样完成:

const Controls = ({ orbitControls, mesh }) => {
    /** @type {THREE.Mesh} */
    const box = mesh.current;

    const { camera } = useThree();
    const code = useCodes();

    // ...your movement code here, remember to replace camera with box.

    // FIXME: Move the Controls component lower down the component tree so that we don't end up with these race conditions.
    if (!!box) {
      box.add(camera);
    }

    // ...animation code
}

这些是我将轨道控件附加到播放器所采取的步骤

OK, so you can see the working version here: https://yvod70.csb.app/

The idea is quite simple, attach the camera to your player/box and then move said object instead of the camera. The camera being a child of the player will be translated and rotated relative to the player.

To do this the first step is to get a reference to the mesh:


const scene = () => {
    const mesh = useRef();

    return (
        <Canvas>
            <mesh
              ref={mesh}
            >
                <boxBufferGeometry args={[1, 1, 1]} />
                <meshBasicMaterial wireframe color={"green"} />
            </mesh>
            <Controls mesh={mesh} />
        </Canvas>
    );
}

After setting this up, we just pass the mesh ref to whatever React component we want and use it however. In our case it's to replace the camera for movement and attach the camera to the box. Which can be done like so in your Controls component:

const Controls = ({ orbitControls, mesh }) => {
    /** @type {THREE.Mesh} */
    const box = mesh.current;

    const { camera } = useThree();
    const code = useCodes();

    // ...your movement code here, remember to replace camera with box.

    // FIXME: Move the Controls component lower down the component tree so that we don't end up with these race conditions.
    if (!!box) {
      box.add(camera);
    }

    // ...animation code
}

These were the steps I took to attach the orbit controls to the player

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文