You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Three.js中几何体与网格的操作及顶点修改后网格更新方法

在Three.js中修改几何体顶点后更新网格的正确姿势

嘿,这个问题我刚好熟!在Three.js里操作几何体顶点后要让网格同步更新,得分你用的是旧版的Geometry还是现在官方主推的BufferGeometry来分别处理,我给你拆解清楚:

一、如果你用的是旧版THREE.Geometry

这种几何体是基于顶点对象数组的,当你手动遍历修改了geometry.vertices里每个顶点的position之后,Three.js并不会自动感知到变化——你得主动告诉它数据更新了:

  1. 标记顶点位置需要更新
    调用geometry.verticesNeedUpdate = true;,这会告诉渲染器在下一帧重新读取顶点位置数据。
  2. 如果修改影响了法线,还要更新法线
    要是你的顶点修改改变了面的朝向(比如旋转顶点),得同时设置geometry.normalsNeedUpdate = true;,不然光照效果会出错。

举个实际的代码例子:

// 遍历并旋转每个顶点的逻辑(假设你已经写好这部分)
geometry.vertices.forEach(vertex => {
  vertex.applyAxisAngle(new THREE.Vector3(1, 0, 0), Math.PI / 6);
});

// 关键更新步骤
geometry.verticesNeedUpdate = true;
geometry.normalsNeedUpdate = true; // 按需添加

二、推荐使用的THREE.BufferGeometry

Three.js r125之后Geometry已经被移除了,官方推荐用BufferGeometry(性能更优,适合大规模顶点)。它用缓冲区数组存储顶点数据,更新方式略有不同:

  1. 修改position数组后标记更新
    如果你直接修改了geometry.attributes.position.array里的数值,要设置geometry.attributes.position.needsUpdate = true;
  2. 法线等其他属性同理
    要是修改影响了法线、UV等其他属性,也要给对应的属性设置needsUpdate = true

代码示例:

const positions = geometry.attributes.position.array;
// 遍历修改position数组的逻辑,比如逐个顶点旋转
for (let i = 0; i < positions.length; i += 3) {
  const vertex = new THREE.Vector3(positions[i], positions[i+1], positions[i+2]);
  vertex.applyAxisAngle(new THREE.Vector3(0, 1, 0), Math.PI / 4);
  positions[i] = vertex.x;
  positions[i+1] = vertex.y;
  positions[i+2] = vertex.z;
}

// 标记position属性需要更新
geometry.attributes.position.needsUpdate = true;
// 若法线受影响,同样更新
// geometry.attributes.normal.needsUpdate = true;

额外优化:不用修改顶点的高效变换

如果你只是想让几何体绕某个轴旋转,其实没必要逐个修改顶点——直接操作网格的矩阵会更高效,尤其是复杂几何体:

// 创建一个绕Y轴旋转的矩阵
const rotationMatrix = new THREE.Matrix4().makeRotationY(Math.PI / 3);
// 把旋转矩阵应用到网格的本地矩阵
mesh.matrix.multiply(rotationMatrix);
// 关闭自动矩阵更新,避免覆盖我们手动设置的矩阵
mesh.matrixAutoUpdate = false;

这种方式不需要修改几何体本身,性能更好,还不会影响共享该几何体的其他网格。

小提醒

如果你的几何体被多个网格共享,修改顶点会让所有用它的网格一起变化。如果只想让单个网格的形状改变,记得先克隆几何体:

const clonedGeometry = originalGeometry.clone();
const uniqueMesh = new THREE.Mesh(clonedGeometry, material);
// 现在修改clonedGeometry的顶点,只会影响uniqueMesh

内容的提问来源于stack exchange,提问作者Russell Strauss

火山引擎 最新活动