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

利用three.js在Vue项目中展示重构的stl模型文件

一、目的

   为了在前端页面展示3d打印机打印过程

二、前期准备

完整模型的stl文件和模型切割成的n个stl文件

models文件夹下的文件就是切割后的stl文件

三、代码

<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";
  
  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(0, 20, 50); // 调整相机位置,使其离模型更远
        camera.lookAt(scene.position);
  
        const renderer = new THREE.WebGLRenderer({ antialias: true });
        renderer.setSize(window.innerWidth, 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 STLLoader();
        const models = this.generateModels(); // 生成47个模型的配置
  
        // 状态变量:控制是否开始旋转
        let allModelsLoaded = false;
  
        // 逐层加载模型
        let currentModelIndex = 0;
        const loadNextModel = () => {
          if (currentModelIndex < models.length) {
            const model = models[currentModelIndex];
            loader.load(model.url, (geometry) => {
              geometry.center();
              const material = new THREE.MeshStandardMaterial({
                color: model.color,
                transparent: true, // 启用透明度
                opacity: 0.8, // 设置透明度值
              });
              const mesh = new THREE.Mesh(geometry, material);
              mesh.position.set(...model.position);
              mesh.scale.set(model.scale, model.scale, model.scale);
              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 = [0, -36.5, 0]; // 基础位置,从底部开始
        const spacing = 0.5; // 模型之间的间距
  
        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/castledemo/models/part_${String(i).padStart(6, "0")}.stl`, // 文件名格式为 part_000000.stl 到 part_000046.stl
            position,
            scale: 0.3,
            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>

四、最终效果

五、问题

模型重构出来会存在走位的情况,可能需要根据每个模型文件的实际大小进行调整。


http://www.kler.cn/a/567406.html

相关文章:

  • Java进阶——注解一文全懂
  • AIP-156 单例资源
  • 一周一个Unity小游戏2D反弹球游戏 - 球的死区及球重生
  • React + TypeScript 实现 SQL 脚本生成全栈实践
  • 3D打印涡轮叶片-当传统铸造遇上“不可能任务”
  • Pytest之fixture的常见用法
  • PyTorch 类声明中的 super().__init__()是什么?为什么必须写它?
  • 【Linux】Linux的进程控制
  • MyBatis基础模块-缓存模块
  • 小结:计算机网路中的性能指标小结
  • 8 - PS XADC接口实验
  • 1-kafka单机环境搭建
  • 【Linux】Linux的基本指令(3)
  • React创建项目实用教程
  • c#实现modbus rtu定时采集数据
  • 基于SSM实现的bbs论坛系统功能实现八
  • VSCode 中使用 GitHub Copilot最新版本详解
  • 数据结构课程设计(java实现)---九宫格游戏,也称幻方
  • MCU的GPIO 八种模式
  • java使用word模板填充内容,再生成pdf