如何用Three.js生成由独立网格组成的90度分段圆环?
用Three.js生成独立网格组成的90度分段圆环
ShapeGeometry方案完全可行,下面是具体实现思路和代码:
实现思路
要生成独立的90度分段圆环,核心是为每个分段创建扇形环形的2D路径,再通过ShapeGeometry转换成网格。关键在于准确计算每个分段的角度范围,以及正确绘制环形路径的内外圆弧。
步骤拆解:
- 计算每个分段的有效角度:总角度为90°(
Math.PI/2弧度),减去所有网格间的间距总和后,平均分配给每个网格。 - 为每个分段绘制扇形环形路径:由外圆弧、内圆弧和两条连接直线组成闭合形状。
- 将每个路径转换成独立网格,添加到场景中。
完整代码实现
// 基础场景设置 const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); const renderer = new THREE.WebGLRenderer(); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); camera.position.z = 50; // 生成分段圆环的核心函数 function generateSegmentedTorus(innerRadius, thickness, count, padding) { const totalAngle = Math.PI / 2; // 90度对应的弧度 // 计算每个分段的角度(减去所有间距后的平均角度) const anglePerSegment = (totalAngle - count * padding) / count; for (let i = 0; i < count; i++) { // 计算当前分段的起始和结束角度 const startAngle = i * (anglePerSegment + padding); const endAngle = startAngle + anglePerSegment; // 创建扇形环形的Shape路径 const segmentShape = new THREE.Shape(); const outerRadius = innerRadius + thickness; // 移动到外圆弧起点 const outerStart = new THREE.Vector2( outerRadius * Math.cos(startAngle), outerRadius * Math.sin(startAngle) ); segmentShape.moveTo(outerStart.x, outerStart.y); // 绘制外圆弧 segmentShape.absarc(0, 0, outerRadius, startAngle, endAngle, false); // 直线连接到内圆弧终点 const innerEnd = new THREE.Vector2( innerRadius * Math.cos(endAngle), innerRadius * Math.sin(endAngle) ); segmentShape.lineTo(innerEnd.x, innerEnd.y); // 反向绘制内圆弧,形成闭合路径 segmentShape.absarc(0, 0, innerRadius, endAngle, startAngle, true); // 直线回到起点,完成闭合 segmentShape.lineTo(outerStart.x, outerStart.y); // 创建网格并添加到场景 const geometry = new THREE.ShapeGeometry(segmentShape); // 用随机颜色区分不同网格 const material = new THREE.MeshBasicMaterial({ color: new THREE.Color().setHSL(i/count, 0.8, 0.6), wireframe: false // 改为true可查看路径结构 }); const segmentMesh = new THREE.Mesh(geometry, material); // 如需3D立体效果,替换为ExtrudeGeometry: // const extrudeSettings = { depth: 1, bevelEnabled: false }; // const geometry = new THREE.ExtrudeGeometry(segmentShape, extrudeSettings); scene.add(segmentMesh); } } // 调用示例:内半径10,厚度3,4个分段,每个分段间距0.1弧度(约5.7°) generateSegmentedTorus(10, 3, 4, 0.1); // 渲染循环 function animate() { requestAnimationFrame(animate); renderer.render(scene, camera); } animate();
参数说明
innerRadius:圆环的内半径(从中心到环形内侧的距离)thickness:圆环的径向厚度(环形外侧与内侧的半径差)count:独立网格的数量padding:每个网格之间的间距(单位:弧度,例如0.1≈5.7°)
关键细节
- 使用
absarc绘制圆弧时,最后一个参数控制绘制方向:外圆弧用false(顺时针),内圆弧用true(逆时针),确保路径闭合正确。 - 每个网格都是独立的
Mesh实例,支持单独修改材质、位置或旋转。 - 如果需要立体的环形分段,只需将
ShapeGeometry替换为ExtrudeGeometry,并设置depth参数控制立体厚度。
内容的提问来源于stack exchange,提问作者Marvin
相关产品推荐
相关产品推荐

