解决用three.js展示n个叠加的stl模型文件错位的问题
加载stl时可以明显看到下面有一部分模型是错位的。
将stl文件格式转化为glb
使用免费将 STL 转换为 GLB - ImageToStl
模型就没有错位了
代码如下
<template>
<div ref="threeContainer" class="three-container"></div>
</template>
<script>
import * as THREE from "three";
import { STLLoader } from "three/examples/jsm/loaders/STLLoader.js";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import {GLTFLoader} from "three/examples/jsm/loaders/GLTFLoader.js";
export default {
name: "CastleDemo",
mounted() {
this.initThree();
},
methods: {
initThree() {
const scene = new THREE.Scene();
scene.background = new THREE.Color(0xeeeeee);
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
camera.position.set(-20, -60, 50); // 调整相机位置
camera.lookAt(scene.position);
// camera.lookAt(0,0,20);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(0.5 * window.innerWidth, 0.7 * window.innerHeight);
this.$refs.threeContainer.appendChild(renderer.domElement);
const ambientLight = new THREE.AmbientLight(0x404040, 1);
const pointLight = new THREE.PointLight(0xffffff, 1, 1000);
pointLight.position.set(0, 50, 50);
scene.add(ambientLight, pointLight);
const loader = new GLTFLoader();
const models = this.generateModels();
// 状态变量:控制是否开始旋转
let allModelsLoaded = false;
// 逐层加载模型
let currentModelIndex = 0;
const loadNextModel = () => {
if (currentModelIndex < models.length) {
const model = models[currentModelIndex];
loader.load(model.url, (gltf) => {
const mesh = gltf.scene.children[0]; // 获取加载的模型
mesh.position.set(...model.position);
mesh.scale.set(model.scale, model.scale, model.scale);
// 修改材质颜色
mesh.traverse((child) => {
if (child.isMesh) {
child.material.color.set(model.color);
child.material.transparent = true;
child.material.opacity = 0.8;
}
});
scene.add(mesh);
// 动态更新进度
currentModelIndex++;
loadNextModel();
});
} else {
// 所有模型加载完成
allModelsLoaded = true;
}
};
loadNextModel(); // 开始加载第一个模型
// 添加轨道控制器
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true; // 启用阻尼效果
controls.dampingFactor = 0.25; // 阻尼系数
controls.enableZoom = true; // 允许缩放
controls.enablePan = true; // 允许平移
// 添加旋转逻辑
let rotationSpeed = 0.01; // 旋转速度
function animate() {
requestAnimationFrame(animate);
// 只有在所有模型加载完成后才开始旋转
// if (allModelsLoaded) {
// scene.traverse((object) => {
// if (object.isMesh) {
// object.rotation.y += rotationSpeed; // 绕Y轴旋转
// object.rotation.x += rotationSpeed * 0.5; // 绕X轴旋转
// }
// });
// }
// controls.update(); // 更新轨道控制器
renderer.render(scene, camera);
}
animate();
},
// 生成47个模型的配置
generateModels() {
const models = [];
const basePosition = [-10, 0, -15]; // 基础位置,从底部开始
const spacing = 0.4; // 模型之间的间距
for (let i = 0; i < 72; i++) {
const position = [
basePosition[0], // X轴位置
basePosition[1]+ i * spacing, // Y轴方向排列
basePosition[2] ,
];
const color = this.getColorByIndex(i); // 根据索引计算颜色
models.push({
url: `/3Dmodels/models(glb)/part_${String(i).padStart(6, "0")}.glb`,
position,
scale: 0.5,
color,
});
}
return models;
},
// 根据索引计算颜色
getColorByIndex(index) {
const startColor = 0xffff00; // 起始颜色为黄色
const endColor = 0x00ffff; // 结束颜色为青色
const colorRange = endColor - startColor;
const ratio = index / (47 - 1); // 计算颜色比例
const color = startColor + Math.floor(colorRange * ratio);
return color;
},
},
};
</script>
<style scoped>
.three-container {
background-color: #ffffff;
}
</style>