vue中加载GLB模型,计算模型的长宽高、绘制模型的边框线

news/2024/10/19 13:18:46/

项目环境版本

  • vue:2.6.12
  • threejs: 0.169.0
  • node: 16.20.0

需求背景

  • 主页面点击预览按钮,默认显示弹框,并且加载GLB模型文件
  • 点击弹框中的功能按钮,计算GLB模型的长宽高
  • 点击弹框中的功能按钮,绘制GLB模型的边框线(长方体空间)

效果预览

在这里插入图片描述

实现步骤

1.引入threejs
npm install three --save
2.创建2个Vue组件:
  • Preview.vue:预览弹框
  • LoadGlb.vue:加载Glb模型文件
3.预览弹框功能(详情见代码注释,只写关键部分)
javascript"><template><div><div class="top-btn"><div class="sizeInfo"><template v-if="showExtraModelInfo"><div><span>长:</span>{{ glbSize.x }}m</div><div><span>宽:</span>{{ glbSize.y }}m</div><div><span>高:</span>{{ glbSize.z }}m</div></template></div><img class="pointer" src="@/assets/images/category.png" alt="" @click="toggleShowExtraInfo"></div><!--    加载Glb模型      --><load-glb ref="glbRef" @getSize="getSize" :glb-url="detailInfo.modelGlbPath" v-if="open" /></div>
<template><script>
import LoadGlb from "./LoadGlb.vue";
export default {components: {LoadGlb},data() {glbSize: {}, // 模型的长宽高showExtraModelInfo: false, // 是否显示额外的模型信息,默认不显示open: false,},methods: {// 获取模型的长宽高getSize(e) {this.glbSize = e},// 切换显示额外的模型信息toggleShowExtraInfo() {this.showExtraModelInfo = !this.showExtraModelInfothis.$refs.glbRef.toggleShowOuterLine(this.showExtraModelInfo)}}
}
</script>
4.加载Glb组件(详情见代码注释)
javascript"><template><div ref="threeJsContainer" class="three-js-container"></div>
</template><script>
import * as THREE from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
// 引入轨道控制器扩展库OrbitControls.js
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';export default {props: {// glb模型的网络地址glbUrl: {type: String,required: true}},data() {return {scene: null,camera: null,renderer: null,glbModel: null,outerLine: null, // 外侧边框线,长方体};},mounted() {this.$nextTick(() => {this.initThree();})},methods: {initThree() {// 创建场景this.scene = new THREE.Scene();this.scene.background = new THREE.Color(0xeeeeee);const width = 360; //宽度const height = 360; //高度// 创建灯光const ambientLight = new THREE.AmbientLight(0xffffff, 1);this.scene.add(ambientLight);const directionalLight = new THREE.DirectionalLight(0xffffff, 1);directionalLight.position.set(1, 1, 1);this.scene.add(directionalLight);// 创建相机this.camera = new THREE.PerspectiveCamera(45, width / height, 1, 3000);// 创建渲染器this.renderer = new THREE.WebGLRenderer();this.renderer.setSize(width, height);// 加载GLB模型this.loadGLBModel();this.$refs.threeJsContainer.appendChild(this.renderer.domElement);// 设置相机控件轨道控制器OrbitControlsconst controls = new OrbitControls(this.camera, this.renderer.domElement);// 如果OrbitControls改变了相机参数,重新调用渲染器渲染三维场景controls.addEventListener('change', () => {this.renderer.render(this.scene, this.camera); //执行渲染操作});//监听鼠标、键盘事件},// 加载GLB模型loadGLBModel() {const loader = new GLTFLoader();loader.load(this.glbUrl, (gltf) => {this.glbModel = gltf.scene;const box = new THREE.Box3().setFromObject(gltf.scene);// 计算glb的长宽高const glbSize = {x: Number((box.max.x - box.min.x).toFixed(2)),y: Number((box.max.y - box.min.y).toFixed(2)),z: Number((box.max.z - box.min.z).toFixed(2))}// 绘制边框线,默认不显示this.drawBorder(box.min, box.max)this.$emit('getSize', glbSize)this.scene.add(this.glbModel);// 动态计算相机位置,保持中心始终看到大小相同的模型,todo: 待优化const { x, y, z } = glbSizeconsole.log('glbSize', glbSize)this.camera.position.set(-x * 1.8, y * 1.4, z * 2);this.camera.lookAt(0, 0, 0);this.animate(this.renderer, this.scene, this.camera);});},// 画模型的边框线drawBorder(min, max) {// 定义长方体的8个顶点坐标const vertices = new Float32Array([// 顶面四个顶点min.x, max.y, min.z, // 0max.x, max.y, min.z,  // 1max.x, max.y, max.z,   // 2min.x, max.y, max.z,  // 3// 底面四个顶点min.x, min.y, min.z, // 4max.x, min.y, min.z,  // 5max.x, min.y, max.z,   // 6min.x, min.y, max.z   // 7]);// 定义顶点索引,用于构成长方体的12条边const indices = new Uint16Array([0, 1, 1, 2, 2, 3, 3, 0, // 顶面边4, 5, 5, 6, 6, 7, 7, 4, // 底面边0, 4, 1, 5, 2, 6, 3, 7  // 竖直边]);// 创建一个BufferGeometryconst geometry = new THREE.BufferGeometry();geometry.setAttribute('position', new THREE.BufferAttribute(vertices, 3));geometry.setIndex(new THREE.BufferAttribute(indices, 1));// 创建一个材质const material = new THREE.LineBasicMaterial({ color: 0xfdaf58 });// 创建线段this.outerLine = new THREE.LineSegments(geometry, material);// 初始隐藏,点击那个玩意的时候再显示this.outerLine.visible = false;// 将线段添加到场景中this.scene.add(this.outerLine);},animate(renderer, scene, camera) {requestAnimationFrame(() => this.animate(renderer, scene, camera));renderer.render(scene, camera);},// 显示隐藏边框线toggleShowOuterLine(flag) {this.outerLine.visible = flag;}},
};
</script><style scoped>
.three-js-container {width: 360px;height: 360px;
}
</style>

http://www.ppmy.cn/news/1540261.html

相关文章

LeetCode_2235. 两整数相加_java

1、问题 2235. 两整数相加https://leetcode.cn/problems/add-two-integers/ 给你两个整数 num1 和 num2&#xff0c;返回这两个整数的和。 示例 1&#xff1a; 输入&#xff1a;num1 12, num2 5 输出&#xff1a;17 解释&#xff1a;num1 是 12&#xff0c;num2 是 5 &am…

SpringTask的学习

cron表达式 cron表达式其实就是一个字符串&#xff0c;通过cron表达式可以定义任务触发的时间,构成规则:分为6或7个 域&#xff0c;由空格分隔开&#xff0c;每个域代表一个含义每个域的含义分别为:秒、分钟、小时、日、月、周、年(可选) cron表达式在线生成器: https://cron…

Matching——网络游戏大厅匹配设计

众所周知&#xff0c;网络游戏大厅匹配系统&#xff0c;一直是游戏很最重要的一环&#xff01;在很多游戏中都是必不可少的的一环。比如&#xff0c;MOBA类 Dota&#xff0c;LOL&#xff0c;吃鸡 大地图这类&#xff0c;都少不了匹配&#xff0c;在服务器设计中也就成了很重要的…

2.计算机网络_IP地址

IPv4的IP地址 1、分类IP IP地址的表示方式&#xff1a; IP地址在整个互联网中是唯一的&#xff0c;指明了连接到某个网络上的一个主机。IP地址用32位二进制数表示&#xff0c;每一个字节代表一段&#xff0c;如下图IP地址即为128.11.3.31。 什么是多归属主机&#xff1a; 当…

重学SpringBoot3-集成Spring Security(一)

更多SpringBoot3内容请关注我的专栏&#xff1a;《SpringBoot3》 期待您的点赞&#x1f44d;收藏⭐评论✍ 重学SpringBoot3-集成Spring Security&#xff08;一&#xff09; 1. 简介与概念2. 基础配置2.1. 添加依赖2.1 基本认证与授权配置 3. 密码加密3.1. 如何加密用户密码3.2…

Git 可视化的实现:提升版本控制体验的利器

Git 是目前最流行的分布式版本控制系统&#xff0c;广泛应用于软件开发和项目管理中。然而&#xff0c;对于许多人来说&#xff0c;Git 命令行操作可能有些复杂且难以直观理解&#xff0c;特别是当涉及到复杂的分支和合并操作时。为了更好地帮助开发者掌握 Git 的操作过程&…

浅谈C#之抽象类、抽象方法

一、基本介绍 在C#中&#xff0c;抽象类和抽象方法是面向对象编程中的重要概念&#xff0c;它们提供了一种方式来定义一个类的基本框架&#xff0c;但不完全实现它。这允许其他类继承这个框架&#xff0c;并提供具体的实现细节。 二、基本用法 抽象类 抽象类是一个不能被实例…

iPad备份软件哪个好?好用的苹果备份软件推荐

苹果手机在将数据备份到电脑时&#xff0c;需要通过第三方的管理软件&#xff0c;才可以将手机连接到电脑进行备份。苹果手机备份软件有很多&#xff0c;常用的有&#xff1a;爱思助手、iMazing、iTuns等。那么这三款常用的备份软件究竟哪款更好呢&#xff1f;下面就给大家盘点…