当前位置: 首页 > news >正文

解决用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>

相关文章:

  • ubuntu qt工程打包后续:桌面快捷方式、开机登陆桌面后自动运行
  • OpenCV图像拼接(1)自动校准之校准旋转相机的函数calibrateRotatingCamera()
  • 在线JSON格式校验工具站
  • 详细介绍IDI_APPLICATION和IDC_ARROW
  • ubuntu20.04使用matlab2024a快捷键调整
  • Python 爬取 1688 关键词搜索接口数据返回说明
  • vue el-table 设置selection选中状态
  • MySql面试总结(三)
  • matlab近似计算联合密度分布
  • 阿里云国际站代理商:如何构建交互式安全分析看板?
  • vue3+el-cascader-panel+多选+动态加载+默认展开+选中查询节点并展开+查询到的这一条自动滚动到顶部+tooltip效果
  • 高铁监控存储扩容-DS SAN存储磁盘阵列
  • Python中数据结构元组详解
  • LangChain开发(一)介绍和第一个例子
  • 什么是 BA ?BA怎么样?BA和BI是什么关系?
  • Nginx的HTTPS配置
  • 【论文笔记】Transformer
  • OpenCV专利收费免费模块介绍
  • QT二 QT使用generate form 生成常用UI,各种UI控件
  • Function Calling的核心机制与挑战
  • 极限拉扯上任巴西,安切洛蒂开启夏窗主帅大挪移?
  • 摩根士丹利:对冲基金已加码,八成投资者有意近期增配中国
  • 再获殊荣!IP SH跻身上海文化品牌全球传播力TOP 6
  • 《AI×SCIENCE十大前沿观察》9:合成数据和数据基础设施
  • 人民日报读者点题·共同关注:今天我们为什么还需要图书馆?
  • 重庆荣昌区委区政府再设“答谢宴”,邀请800余名志愿者机关食堂用餐