102 lines
3.4 KiB
JavaScript
102 lines
3.4 KiB
JavaScript
import * as THREE from 'three';
|
|
|
|
class HexNutGeometry extends THREE.BufferGeometry {
|
|
constructor(radius = 1, height = 0.5, holeRadius = 0.6) {
|
|
super();
|
|
|
|
this.parameters = {
|
|
radius: radius,
|
|
height: height,
|
|
holeRadius: holeRadius
|
|
};
|
|
|
|
this.buildGeometry();
|
|
}
|
|
|
|
buildGeometry() {
|
|
const radius = this.parameters.radius;
|
|
const height = this.parameters.height;
|
|
const holeRadius = this.parameters.holeRadius;
|
|
|
|
const vertices = [];
|
|
const indices = [];
|
|
|
|
// 1. 定义六边形的顶点 (顶部和底部)
|
|
for (let i = 0; i < 6; i++) {
|
|
const angle = (Math.PI * 2 / 6) * i;
|
|
const x = radius * Math.cos(angle);
|
|
const y = radius * Math.sin(angle);
|
|
|
|
// 顶部顶点
|
|
vertices.push(x, y, height / 2);
|
|
// 底部顶点
|
|
vertices.push(x, y, -height / 2);
|
|
}
|
|
|
|
// 内部孔洞的顶点 (顶部和底部)
|
|
for (let i = 0; i < 32; i++) { // 使用更多分段来近似圆形
|
|
const angle = (Math.PI * 2 / 32) * i;
|
|
const x = holeRadius * Math.cos(angle);
|
|
const y = holeRadius * Math.sin(angle);
|
|
|
|
// 顶部内侧顶点
|
|
vertices.push(x, y, height / 2); // 索引从 12 开始
|
|
// 底部内侧顶点
|
|
vertices.push(x, y, -height / 2); // 索引从 12 + 32 开始
|
|
}
|
|
|
|
// 2. 定义侧面
|
|
for (let i = 0; i < 6; i++) {
|
|
const currentTop = i * 2;
|
|
const nextTop = ((i + 1) % 6) * 2;
|
|
const currentBottom = i * 2 + 1;
|
|
const nextBottom = ((i + 1) % 6) * 2 + 1;
|
|
|
|
// 两个三角形组成一个侧面
|
|
indices.push(currentTop, nextTop, currentBottom);
|
|
indices.push(nextTop, nextBottom, currentBottom);
|
|
}
|
|
|
|
// 3. 定义顶部和底部 (六边形扇面 - 注意避开中心孔洞)
|
|
// 顶部
|
|
for (let i = 0; i < 6; i++) {
|
|
const current = i * 2;
|
|
const next = ((i + 1) % 6) * 2;
|
|
// 使用孔洞边缘的顶点来创建顶部面
|
|
const holeIndex1 = 12 + i * 2;
|
|
const holeIndex2 = 12 + ((i + 1) % 32) * 2; // 注意孔洞分段数
|
|
|
|
indices.push(current, next, holeIndex1);
|
|
indices.push(next, holeIndex2, holeIndex1);
|
|
}
|
|
|
|
// 底部
|
|
for (let i = 0; i < 6; i++) {
|
|
const current = i * 2 + 1;
|
|
const next = ((i + 1) % 6) * 2 + 1;
|
|
// 使用孔洞边缘的顶点来创建底面
|
|
const holeIndex1 = 12 + 64 + i * 2;
|
|
const holeIndex2 = 12 + 64 + ((i + 1) % 32) * 2; // 注意孔洞分段数
|
|
|
|
indices.push(current, holeIndex1, next);
|
|
indices.push(holeIndex1, holeIndex2, next);
|
|
}
|
|
|
|
// 4. 定义内部孔洞的侧面
|
|
for (let i = 0; i < 32; i++) {
|
|
const currentTop = 12 + i * 2;
|
|
const nextTop = 12 + ((i + 1) % 32) * 2;
|
|
const currentBottom = 12 + 64 + i * 2;
|
|
const nextBottom = 12 + 64 + ((i + 1) % 32) * 2;
|
|
|
|
indices.push(currentTop, nextTop, currentBottom);
|
|
indices.push(nextTop, nextBottom, currentBottom);
|
|
}
|
|
|
|
this.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3));
|
|
this.setIndex(indices);
|
|
this.computeVertexNormals();
|
|
}
|
|
}
|
|
|
|
export { HexNutGeometry }; |