VUE3使用three.js显示3D模型
使用3D模型作为自动化系统的界面已经成为潮流。尽管在AutomationML 中推荐COLLADA作为 3D 模型的标准。但是COLLADA的开发者khronos 集团却已经开发了COLLADA的后继者glTF 。glTF 2.0已经成为国际标准ISO/IEC 12113:2022。
Khronos声称-‘glTF是3D里的JPEG’。目前看来glTF 更加流行。
glTF 概述
glTF 的工业中的应用
CAD 软件的支持
solidworks 2020版 开始支持glTF 的导出。
3D 查看器
windows 上有一个3D查看器,可以显示导出的glTF 3D模型
支持glTF 的3D软件
SketchUp
SketchUp,民间俗称“草图大师”,是全世界极受欢迎的三维建模与设计软件,在全球拥有4千万年度用户。SketchUp在建筑设计、家具设计、展陈设计、电影美术、舞台美术、产品设计、工程设计等领域有广泛的应用。SketchUp由于其简单、易学、灵活等特点,是目前新兴的原生的BIM正向设计工具,尤其在室内装饰、以及其它应用领域。
Blender
Blender 是一款永久开源免费的 3D 创作软件,支持整个 3D 创作流程:建模、雕刻、骨骼装配、动画、模拟、实时渲染、合成和运动跟踪,甚至可用作视频编辑及游戏创建。
Web 前端的支持
Web 前端有一个功能强大的3D 开源库Three.js 支持glTF 的导入。Three.JS 的背后是webGL 技术
WebGL可以为HTML5 Canvas提供硬件3D加速渲染(部分计算GPU),它借助系统显卡来在浏览器里更流畅地展示3D场景和模型了,还能创建复杂的导航和数据视觉化。WebGL的本质 - JavaScript操作OpenGL接口。
Three.js 是一款 webGL(3D绘图标准,在此不赘述)引擎,可以运行于所有支持 webGL 的浏览器。Three.js 封装了 webGL 底层的 API ,为我们提供了高级的开发接口,可以使用简单的代码去实现 3D 渲染。
Three.js 支持glTF 文件的导入。
VUE3+Three.js实验
Step1 安装Three.js
npm install three --save --force
Step2 代码
首先要对下列参数初始化:
- 相机 camera
- 场景 scene
- 渲染器renderer
- 控制 controls,
- 环境光 ambientLight,
- 方向光 directionalLight
渲染器设置事件处理,实现点击对象的操作(OnClick)
遇到的问题
- 物体显示不出来,主要是导入glTF 时model.scale.set(2500, 2500, 2500)缩放比例太小了
- 物体无法通过鼠标旋转,缩放。最后发现是没有设置相机的位置。
camera.position.set(20, 30, 20);
<script setup>
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import { ref, onMounted } from "vue";
let screenDom = ref();
var camera,scene,renderer,controls,ambientLight,directionalLight
onMounted(() => {
scene = new THREE.Scene();
// 创建相机
camera = new THREE.PerspectiveCamera(
135,
screenDom.value.clientWidth / screenDom.value.clientHeight,
0.1,
100
);
camera.position.set(20, 30, 20); //important
// 添加环境光
ambientLight = new THREE.AmbientLight(0xffffff, 0.9);
scene.add(ambientLight);
//
directionalLight = new THREE.DirectionalLight(0xffffff, 0.8); //光源,color:灯光颜色,intensity:光照强度
directionalLight.position.set(400, 200, 300);
scene.add(directionalLight);
// 创建渲染器
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setClearColor(new THREE.Color("#000000"));
renderer.setSize(screenDom.value.clientWidth, screenDom.value.clientHeight);
renderer.domElement.addEventListener("click", onClick, false);
screenDom.value.appendChild(renderer.domElement);
//
controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.enablePan = true;
controls.enableZoom = true;
controls.autoRotate = true;
controls.autoRotateSpeed = 9;
controls.update(); //重新设置轨道,相当于刷新
//添加模型
const loader = new GLTFLoader();
loader.load(
"../../../public/Glasses-v1.glb",
(gltf) => {
// 加载成功后的回调函数
const model = gltf.scene;
model.scale.set(2500, 2500, 2500); // 缩放模型
const box = new THREE.Box3().setFromObject(model);
const center = box.getCenter(new THREE.Vector3());
let axis = new THREE.Vector3(0, 1, 0);
model.rotateOnAxis(axis, Math.PI * 2);
model.position.sub(center); // 将模型位置移到原点处
scene.add(model);
},
(xhr) => {
// 加载过程中的回调函数
console.log((xhr.loaded / xhr.total) * 100 + "% loaded");
},
(error) => {
// 加载失败的回调函数
console.error("Failed to load model", error);
}
);
// 渲染场景
const render = () => {
renderer.render(scene, camera);
controls.update();
requestAnimationFrame(render);
};
render();
});
function onClick() {
event.preventDefault();
const mouse = new THREE.Vector2();
const rect = screenDom.value.getBoundingClientRect()
mouse.x = ((event.clientX+rect.left) / window.innerWidth) * 2 - 1;
mouse.y = -((event.clientY+rect.top)/ window.innerHeight) * 2 + 1;
console.log("x:"+mouse.x,"y:"+mouse.y);
const raycaster = new THREE.Raycaster();
raycaster.setFromCamera(mouse, camera);
var intersects = raycaster.intersectObjects(scene.children); //array
if (intersects.length > 0) {
var selectedObject = intersects[0];
alert(selectedObject.object.name);
}
}
</script>
<template>
<div class="container">
<h2>3D 模型</h2>
<div class="canvas-container" ref="screenDom"></div>
</div>
</template>
<style scoped>
.canvas-container {
width: 800px;
height: 400px;
}
body {
overflow: hidden;
margin: 0px;
}
</style>
最终的界面
小结
开放自动化是一个热门话题,笔者常常想,开放自动化系统的本质是什么?我认为它们本质是使用公共技术实现的系统。其中包括协议,模型的格式和设计工具。并不一定拘泥于某一种单一的技术或者标准,在AI 时代更是如此,只要是公开的技术就能够转换。大胆地使用IT的新技术,解决自动化行业的问题是当下最重要的。
更多推荐
所有评论(0)