three.js - 通过动态更新 TubeBufferGeometry 的曲线创建光迹效果
问题描述
我有一个使用 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 帧以提高性能)上的曲线,并使用索引来跟踪要更新的点数组中的哪个位置。
但是我遇到了两个问题:
- TubeBufferGeometry 不更新。不确定是否可以在实例化后更新几何。
- 我预见到使用这种固定数组/索引方法的缺陷是,一旦我到达数组的末尾,我将不得不绕回索引 0。所以曲线插值会搞砸,因为我假设它需要点依次。数组中的最后一个点现在应该连接到第一个点,但不会那样。
为了解决#2,我尝试了类似
points.unshift();
points.push(point.clone);
而不是,points[index].copy(point);
但我仍然无法让 Tube 首先更新。
我想看看是否有更好的解决方案,或者这是否是解决此类问题的正确方法。
解决方案
如果要更新 TubeBufferGeometry 的路径,还需要更新所有的顶点和法线,就像重新构建几何体一样。
看看这里了解它是如何工作的:https ://github.com/mrdoob/three.js/blob/r118/src/geometries/TubeGeometry.js#L135
重要的部分是generateSegment()
功能,之前不要忘记这部分:
const frames = path.computeFrenetFrames( tubularSegments, closed );
我去年做了一个例子,随意使用我的代码:https ://codepen.io/soju22/pen/JzzvbR
推荐阅读
- php - file_put_contents, file_append 如何写入内容 DESC
- c++ - 如何找到第二小的向量?
- c# - Xaml UI Designer 对于 .net core 3.0 中的 wpf 项目不活动
- javascript - Cookie 在同意之前设置
- microsoft-graph-api - 图表 - 是否有更简单/更快的方法来删除 SharePoint 列表中的所有项目?
- video - 使用 FFmpeg 创建单个视频表单 3 个单独的视频
- java - YAML 文件:读取 Yaml 文件并以相同格式写入文件
- swift - 了解闭包的目的
- httpclient - 在 Apache HttpClient 中,我如何知道 2 个请求是否使用相同的连接?
- sql - PostgreSQL 错误:返回集合的函数必须出现在 FROM 的顶层