gpt4 book ai didi

three.js - 如何使用可以通过轨道控制移动的正交相机在 react 三/纤维中拖动 x 和 z 中受 y 约束的对象?

转载 作者:行者123 更新时间:2023-12-02 01:57:40 28 4
gpt4 key购买 nike

我希望能够使用 React-three-fiber 和正交相机将对象拖过 Canvas 中的平面(想想棋盘上的棋子)。

这是一个使用固定相机位置的示例(不是我的):https://codepen.io/kaolay/pen/bqKjVz

但我也希望能够移动相机 - 所以我添加了 Orbitcontrols,当对象被拖动时这些控件会被禁用。

我这里有一个代码沙箱,我的尝试基于许多其他示例: https://codesandbox.io/s/inspiring-franklin-2r3ri?file=/src/Obj.jsx

主要代码在两个文件中,带有 Canvas 、相机和轨道控件的 App.jsx。 Obj.jsx 具有被拖动的网格以及使用手势 useDrag 函数内的拖动逻辑。

应用程序.jsx

import React, { useState } from "react";
import { Canvas } from "@react-three/fiber";
import Obj from "./Obj.jsx";
import { OrthographicCamera, OrbitControls } from "@react-three/drei";
import * as THREE from "three";

export default function App() {
const [isDragging, setIsDragging] = useState(false);

return (
<Canvas style={{ background: "white" }} shadows dpr={[1, 2]}>
<ambientLight intensity={0.5} />
<directionalLight
intensity={0.5}
castShadow
shadow-mapSize-height={512}
shadow-mapSize-width={512}
/>

<mesh rotation={[-Math.PI / 2, 0, 0]} receiveShadow>
<planeBufferGeometry attach="geometry" args={[10, 10]} receiveShadow />
<meshPhongMaterial
attach="material"
color="#ccc"
side={THREE.DoubleSide}
receiveShadow
/>
</mesh>

<Obj setIsDragging={setIsDragging} />

<OrthographicCamera makeDefault zoom={50} position={[0, 40, 200]} />

<OrbitControls minZoom={10} maxZoom={50} enabled={!isDragging} />
</Canvas>
);
}

Obj.jsx(在 Use Drag 函数中有违规代码)

import React, { useState } from "react";
import { useDrag } from "@use-gesture/react";
import { animated, useSpring } from "@react-spring/three";
import { useThree } from "@react-three/fiber";
import * as THREE from "three";

function Obj({ setIsDragging }) {
const { camera } = useThree();
const [pos, setPos] = useState([0, 1, 0]);
const { size, viewport } = useThree();
const aspect = size.width / viewport.width;
const [spring, api] = useSpring(() => ({
// position: [0, 0, 0],
position: pos,
scale: 1,
rotation: [0, 0, 0],
config: { friction: 10 }
}));
const bind = useDrag(
({ active, delta, movement: [x, y], velocity, timeStamp, memo = 0 }) => {
if (active) {

//// THIS IS THE CODE THAT I KNOW IS NOT WORKING /////

let vDir = new THREE.Vector3();
let vPos = new THREE.Vector3(
(x / window.innerWidth) * 2 - 1,
-(y / window.innerHeight) * 2 + 1,
0.5
).unproject(camera);

vDir.copy(vPos).sub(camera.position).normalize();
let flDistance = -camera.position.z / vDir.z;
vPos = vPos.copy(camera.position).add(vDir.multiplyScalar(flDistance));
const arbitraryFactor = 1; // I suspect this has to reflect the distance from camera in all dims...
setPos([vPos.x * arbitraryFactor, 1.5, -vPos.y * arbitraryFactor]);

//// END /////
}

setIsDragging(active);

api.start({
// position: active ? [x / aspect, -y / aspect, 0] : [0, 0, 0],
position: pos,
scale: active ? 1.2 : 1,
rotation: [y / aspect, x / aspect, 0]
});
return timeStamp;
}
);

return (
<animated.mesh {...spring} {...bind()} castShadow>
<dodecahedronBufferGeometry
castShadow
attach="geometry"
args={[1.4, 0]}
/>
<meshNormalMaterial attach="material" />
</animated.mesh>
);
}

export default Obj;

一些有用的引用资料,但还没有让我到达那里! Mouse / Canvas X, Y to Three.js World X, Y, Z

https://codesandbox.io/s/react-three-fiber-gestures-forked-lpfv3?file=/src/App.js:1160-1247

https://codesandbox.io/embed/react-three-fiber-gestures-08d22?codemirror=1

https://codesandbox.io/s/r3f-lines-capture-1gkvp

https://github.com/pmndrs/react-three-fiber/discussions/641

最后再次重新链接到我的代码沙箱示例: https://codesandbox.io/s/inspiring-franklin-2r3ri?file=/src/Obj.jsx:0-1848

最佳答案

在意识到 React-Three-Fiber 将事件信息传递给 useDrag 后,我采取了不同的方法,其中包含我需要的坐标和射线信息。

https://codesandbox.io/s/musing-night-wso9v?file=/src/App.jsx

应用程序.jsx

import React, { useState } from "react";
import { Canvas } from "@react-three/fiber";
import Obj from "./Obj.jsx";
import { OrthographicCamera, OrbitControls } from "@react-three/drei";
import * as THREE from "three";

export default function App() {
const [isDragging, setIsDragging] = useState(false);
const floorPlane = new THREE.Plane(new THREE.Vector3(0, 1, 0), 0);

return (
<Canvas style={{ background: "white" }} shadows dpr={[1, 2]}>
<ambientLight intensity={0.5} />
<directionalLight
intensity={0.5}
castShadow
shadow-mapSize-height={512}
shadow-mapSize-width={512}
/>

<mesh
rotation={[-Math.PI / 2, 0, 0]}
position={[0, -0.1, 0]}
receiveShadow
>
<planeBufferGeometry attach="geometry" args={[10, 10]} receiveShadow />
<meshPhongMaterial
attach="material"
color="#ccc"
side={THREE.DoubleSide}
receiveShadow
/>
</mesh>

<planeHelper args={[floorPlane, 5, "red"]} />

<gridHelper args={[100, 100]} />

<Obj setIsDragging={setIsDragging} floorPlane={floorPlane} />

<OrthographicCamera makeDefault zoom={50} position={[0, 40, 200]} />

<OrbitControls minZoom={10} maxZoom={50} enabled={!isDragging} />
</Canvas>
);
}

对象.jsx

import React, { useState, useRef } from "react";
import { useDrag } from "@use-gesture/react";
import { animated, useSpring } from "@react-spring/three";
import { useThree } from "@react-three/fiber";
import * as THREE from "three";

function Obj({ setIsDragging, floorPlane }) {
const [pos, setPos] = useState([0, 1, 0]);
const { size, viewport } = useThree();
const aspect = size.width / viewport.width;

let planeIntersectPoint = new THREE.Vector3();

const dragObjectRef = useRef();

const [spring, api] = useSpring(() => ({
// position: [0, 0, 0],
position: pos,
scale: 1,
rotation: [0, 0, 0],
config: { friction: 10 }
}));

const bind = useDrag(
({ active, movement: [x, y], timeStamp, event }) => {
if (active) {
event.ray.intersectPlane(floorPlane, planeIntersectPoint);
setPos([planeIntersectPoint.x, 1.5, planeIntersectPoint.z]);
}

setIsDragging(active);

api.start({
// position: active ? [x / aspect, -y / aspect, 0] : [0, 0, 0],
position: pos,
scale: active ? 1.2 : 1,
rotation: [y / aspect, x / aspect, 0]
});
return timeStamp;
},
{ delay: true }
);

return (
<animated.mesh {...spring} {...bind()} castShadow>
<dodecahedronBufferGeometry
ref={dragObjectRef}
attach="geometry"
args={[1.4, 0]}
/>
<meshNormalMaterial attach="material" />
</animated.mesh>
);
}

export default Obj;

这不应该花我那么长时间,我希望这对其他人有帮助!

关于three.js - 如何使用可以通过轨道控制移动的正交相机在 react 三/纤维中拖动 x 和 z 中受 y 约束的对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69414101/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com