通过动态更新TubeBufferGeometry的曲线来创建光迹效果

时间:2020-07-23 01:18:53

标签: three.js react-three-fiber

我有一个使用“反应三纤维”的第三人称游戏,我想在玩家移动的任何地方添加一种尾灯效果。光迹会在一段时间后消失,因此我考虑为这些点使用固定大小的数组。这是我最初尝试的解决方案:

const point = new THREE.Vector3();
const points = new Array(50).fill(null).map(p => new THREE.Vector3());
let index = 0;


const Trail = () => {
    const ref = useRef();
    const playerBody = useStore(state => state.player); // contains player position

    const [path, setPath] = useState(new THREE.CatmullRomCurve3(points));
    useFrame(() => { // equivalent to raf
        const { x, y, z } = playerBody.position;
        point.set(x, y, z);

        points[index].copy(point);
        index = (index + 1) % 50;

        setPath(new THREE.CatmullRomCurve3(points));

        if (ref && ref.current) {
            ref.current.attributes.position.needsUpdate = true;
            ref.current.computeBoundingSphere();
        }
    });

    return (
        <mesh>
            <tubeBufferGeometry ref={ref} attach="geometry" args={[path, 20, .5, 8, false]} />
            <meshBasicMaterial attach="material" color={0xffffff} />
        </mesh>
    )
}

基本上,我的思维过程是更新每帧(或每x帧以获得更好的性能)上的曲线,并使用索引来跟踪要更新的点阵列中的哪个位置。

但是我遇到两个问题:

  1. TubeBufferGeometry不更新。不确定实例化后是否甚至可以更新几何。
  2. 使用这种固定的数组/索引方法时遇到的陷阱是,一旦我击中数组的末尾,我将不得不回绕到索引0。因此,曲线插值会弄乱,因为我假设它是按顺序取分数。数组中的最后一个点现在应该连接到第一个点,但事实并非如此。

要解决#2,我尝试了类似的方法

points.unshift();
points.push(point.clone);

而不是points[index].copy(point);,但我仍然无法首先更新Tube。

我想看看是否有更好的解决方案,或者这是否是解决此类问题的正确方法。

1 个答案:

答案 0 :(得分:0)

如果要更新TubeBufferGeometry的路径,则还需要更新所有顶点和法线,就像重新构建几何一样。

在这里看看它是如何工作的:https://github.com/mrdoob/three.js/blob/r118/src/geometries/TubeGeometry.js#L135

重要的部分是Private oEnvironMap As New SortedDictionary(Of String, String) Private oEnvironMap As SortedDictionary(Of String, String) = New SortedDictionary(Of String, String) 函数,不要忘了这部分:

generateSegment()

我去年做了一个例子,随时使用我的代码:https://codepen.io/soju22/pen/JzzvbR