使用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的新技术,解决自动化行业的问题是当下最重要的。

   

    

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐