分离模型
This commit is contained in:
43
index.html
43
index.html
@@ -13,6 +13,8 @@
|
||||
</style>
|
||||
<script type="module">
|
||||
import * as THREE from 'three';
|
||||
import { CSGHexNutGeometry } from './objects/育苗盘.js';
|
||||
import { 六角螺丝帽 } from './objects/螺丝帽.js';
|
||||
|
||||
// 1. 初始化场景、相机和渲染器
|
||||
const scene = new THREE.Scene();
|
||||
@@ -21,21 +23,23 @@
|
||||
renderer.setSize(window.innerWidth, window.innerHeight);
|
||||
document.body.appendChild(renderer.domElement);
|
||||
|
||||
// 2. 添加立方体(立方体:红色,中等粗糙度,高金属感)
|
||||
const cube = new THREE.Mesh(
|
||||
new THREE.BoxGeometry(1, 1, 1),
|
||||
new THREE.MeshStandardMaterial({ color: 0xff0000, roughness: 0.5, metalness: 0.8 })
|
||||
);
|
||||
scene.add(cube);
|
||||
//// 2. 添加立方体(立方体:红色,中等粗糙度,高金属感)
|
||||
//const cube = new THREE.Mesh(
|
||||
// new THREE.BoxGeometry(1, 1, 1),
|
||||
// new THREE.MeshStandardMaterial({ color: 0xff0000, roughness: 0.5, metalness: 0.8 })
|
||||
//);
|
||||
//scene.add(cube);
|
||||
|
||||
// 添加地面(平面:红色,中等粗糙度,高金属感)
|
||||
const plane = new THREE.Mesh(
|
||||
new THREE.PlaneGeometry(10, 10),
|
||||
new THREE.MeshStandardMaterial({ color: 0x808080, roughness: 0.5, metalness: 0.8 })
|
||||
//// 添加育苗盘
|
||||
//const 育苗盘模型 = 育苗盘();
|
||||
//scene.add(育苗盘模型);
|
||||
|
||||
// 添加螺丝帽
|
||||
const 螺丝帽模型 = new THREE.Mesh(
|
||||
new 六角螺丝帽(1, 0.5, 0.6),
|
||||
new THREE.MeshStandardMaterial({ color: 0x00ff00, roughness: 0.5, metalness: 0.8 })
|
||||
);
|
||||
plane.rotation.x = -Math.PI / 2; // 旋转地面,使其水平
|
||||
plane.position.y = -1; // 将地面放置在立方体下方
|
||||
scene.add(plane);
|
||||
scene.add(螺丝帽模型);
|
||||
|
||||
// 添加光源
|
||||
scene.add(new THREE.AmbientLight(0x404040, 1)); // 环境光,柔和的白光
|
||||
@@ -48,8 +52,17 @@
|
||||
// 3. 动画循环
|
||||
function animate() {
|
||||
requestAnimationFrame(animate);
|
||||
cube.rotation.x += 0.01;
|
||||
cube.rotation.y += 0.01;
|
||||
//cube.rotation.x += 0.01;
|
||||
//cube.rotation.y += 0.01;
|
||||
|
||||
//// 旋转育苗盘
|
||||
//育苗盘模型.rotation.x += 0.01;
|
||||
//育苗盘模型.rotation.y += 0.01;
|
||||
|
||||
// 旋转螺丝帽
|
||||
螺丝帽模型.rotation.x += 0.01;
|
||||
螺丝帽模型.rotation.y += 0.01;
|
||||
|
||||
renderer.render(scene, camera);
|
||||
}
|
||||
animate();
|
||||
|
102
objects/DEMO.js
Normal file
102
objects/DEMO.js
Normal file
@@ -0,0 +1,102 @@
|
||||
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 };
|
47
objects/育苗盘.js
Normal file
47
objects/育苗盘.js
Normal file
@@ -0,0 +1,47 @@
|
||||
import * as THREE from 'three';
|
||||
import { SUBTRACTION, Brush, Evaluator } from 'three-bvh-csg';
|
||||
|
||||
class CSGHexNutGeometry 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 hexagonGeometry = new THREE.CylinderGeometry(radius, radius, height, 6, 1, false);
|
||||
const hexagonMesh = new THREE.Mesh(hexagonGeometry); // 注意这里没有材质
|
||||
const hexagonBrush = new Brush(hexagonMesh.geometry); // 使用 Brush 构造函数
|
||||
|
||||
// 创建内部的孔洞 (圆柱体)
|
||||
const holeHeight = height + 0.1;
|
||||
const holeGeometry = new THREE.CylinderGeometry(holeRadius, holeRadius, holeHeight, 32);
|
||||
const holeMesh = new THREE.Mesh(holeGeometry); // 注意这里没有材质
|
||||
const holeBrush = new Brush(holeMesh.geometry); // 使用 Brush 构造函数
|
||||
|
||||
// 执行布尔运算 (差集)
|
||||
const evaluator = new Evaluator();
|
||||
const resultBrush = evaluator.evaluate(hexagonBrush, holeBrush, SUBTRACTION);
|
||||
|
||||
// 将布尔运算结果转换为 BufferGeometry
|
||||
const finalGeometry = resultBrush.geometry;
|
||||
|
||||
// 将结果的属性复制到当前的 BufferGeometry 实例
|
||||
this.setAttribute('position', finalGeometry.getAttribute('position'));
|
||||
this.setIndex(finalGeometry.getIndex());
|
||||
this.computeVertexNormals(); // 计算法线
|
||||
}
|
||||
}
|
||||
|
||||
export { CSGHexNutGeometry };
|
35
objects/螺丝帽.js
Normal file
35
objects/螺丝帽.js
Normal file
@@ -0,0 +1,35 @@
|
||||
import * as THREE from 'three';
|
||||
import { SUBTRACTION, Brush, Evaluator } from 'three-bvh-csg';
|
||||
|
||||
export class 六角螺丝帽 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, height, holeRadius } = this.parameters;
|
||||
|
||||
// 创建螺丝帽主体 (六棱柱)
|
||||
const hexagonBrush = new Brush(new THREE.CylinderGeometry(radius, radius, height, 6));
|
||||
|
||||
// 创建内部的孔洞 (圆柱体)
|
||||
const holeBrush = new Brush(new THREE.CylinderGeometry(holeRadius, holeRadius, height + 0.1, 128));
|
||||
|
||||
// 执行布尔运算 (差集)
|
||||
const resultBrush = new Evaluator().evaluate(hexagonBrush, holeBrush, SUBTRACTION);
|
||||
|
||||
// 将布尔运算结果应用到当前 BufferGeometry
|
||||
this.copy(resultBrush.geometry);
|
||||
this.computeVertexNormals(); // 计算法线
|
||||
}
|
||||
}
|
||||
|
||||
export default { 六角螺丝帽 };
|
@@ -2,7 +2,8 @@
|
||||
"name": "farm",
|
||||
"version": "1.0.0",
|
||||
"description": "农场",
|
||||
"main": "index.js",
|
||||
"main": "main.js",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite"
|
||||
},
|
||||
@@ -16,6 +17,7 @@
|
||||
"vite": "^6.3.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"three": "^0.176.0"
|
||||
"three": "^0.176.0",
|
||||
"three-bvh-csg": "^0.0.17"
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user