默认物体均为居中,如果指定位置没有发生偏移,可能是因为在执行布尔操作之前没有正确设置变换。确保在进行布尔运算之前应用所有必要的变换。以下是经过修正的完整代码示例,它会确保圆柱正确旋转并与盒子进行 CSG 操作。
安装依赖
首先,确保安装了必要的依赖:
npm install three three-csg-ts
创建 Vue 组件
在 src
目录下创建一个新的组件文件 ThreeScene.vue
,并在其中实现 Three.js 渲染和 three-csg-ts
操作。
以下是 ThreeScene.vue
的代码示例:
<template>
<div ref="threeContainer" class="three-container"></div>
</template>
<script lang="ts">
import { defineComponent, onMounted, ref } from 'vue';
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import { CSG } from 'three-csg-ts';
export default defineComponent({
name: 'ThreeScene',
setup() {
const threeContainer = ref<HTMLDivElement | null>(null);
onMounted(() => {
if (!threeContainer.value) return;
// 创建场景、相机和渲染器
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);
threeContainer.value.appendChild(renderer.domElement);
// 添加轨道控制
const controls = new OrbitControls(camera, renderer.domElement);
// 创建一个盒子
const boxGeometry = new THREE.BoxGeometry(2, 2, 2);
const boxMaterial = new THREE.MeshStandardMaterial({ color: 0x00ff00 });
const boxMesh = new THREE.Mesh(boxGeometry, boxMaterial);
// 创建一个圆柱
const cylinderGeometry = new THREE.CylinderGeometry(0.5, 0.5, 2, 32);
const cylinderMaterial = new THREE.MeshStandardMaterial({ color: 0xff0000 });
const cylinderMesh = new THREE.Mesh(cylinderGeometry, cylinderMaterial);
cylinderMesh.rotation.z = Math.PI / 2;
cylinderMesh.position.x = -0.5; // 调整位置使其在左半边
// 更新圆柱的变换矩阵
cylinderMesh.updateMatrix();
// 执行 CSG 操作
const boxCSG = CSG.fromMesh(boxMesh);
const cylinderCSG = CSG.fromMesh(cylinderMesh);
const subtractedCSG = boxCSG.subtract(cylinderCSG);
// 转换回 Three.js 网格
const resultMesh = CSG.toMesh(subtractedCSG, boxMesh.matrix);
resultMesh.material = boxMaterial; // 应用相同的材质
scene.add(resultMesh);
// 添加光源
const light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(5, 5, 5).normalize();
scene.add(light);
camera.position.z = 5;
const animate = () => {
requestAnimationFrame(animate);
resultMesh.rotation.x += 0.01;
resultMesh.rotation.y += 0.01;
controls.update();
renderer.render(scene, camera);
};
animate();
// 处理窗口大小调整
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
});
return {
threeContainer,
};
},
});
</script>
<style>
.three-container {
width: 100%;
height: 100vh;
}
</style>
整合到主应用
确保在你的主应用组件(例如 App.vue
)中使用 ThreeScene
组件:
<template>
<div id="app">
<ThreeScene />
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import ThreeScene from './components/ThreeScene.vue';
export default defineComponent({
name: 'App',
components: {
ThreeScene,
},
});
</script>
<style>
#app {
width: 100%;
height: 100vh;
margin: 0;
}
</style>
总结
代码确保在进行 CSG 操作之前正确设置和更新了圆柱体的变换矩阵。这样,圆柱体的旋转和位置调整可以正确应用,从而在正方体的左半边进行交互式挖洞。
这里要注意,如需移动物体,在非居中位置进行挖洞,在合理的位置添加以下代码,否则无法再指定位置进行开挖
// 更新圆柱的变换矩阵
cylinderMesh.updateMatrix();