工业机械产品大多体积庞大、运输成本高,在参加行业展会或向海外客户销售时,如果没有实物展示,仅凭静态、简单的图片说明书介绍,无法让客户全面了解产品,不仅工作人员制作麻烦,客户看得也费力。如果能在 Web 上做 3D 设备展示,销售人员可以不限平台随时给客户介绍演示。还可以不受现实条件限制,演示设备拆分和组装的过程,展示产品内部结构和动态运作时的效果,让客户更直观了解产品的部件组成,更准确、全面地了解产品的功能和特点,大大降低了沟通成本。为了解决这些行业痛点,本篇文章采用 Hightopo 的 HT for Web 产品实现了一个发动机设备 3D 可视化案例。

    工业机械产品大多体积庞大、运输成本高,在参加行业展会或向海外客户销售时,如果没有实物展示,仅凭静态、简单的图片说明书介绍,无法让客户全面了解产品,不仅工作人员制作麻烦,客户看得也费力。如果能在 Web 上做 3D 设备展示,销售人员可以不限平台随时给客户介绍演示。还可以不受现实条件限制,演示设备拆分和组装的过程,展示产品内部结构和动态运作时的效果,让客户更直观了解产品的部件组成,更准确、全面地了解产品的功能和特点,大大降低了沟通成本。为了解决这些行业痛点,本篇文章采用 Hightopo 的 HT for Web 产品实现了一个发动机设备 3D 可视化案例。

预览地址:基于 HTML5 WebGL  的发动机 3D 可视化系统( http://www.hightopo.com/demo/engine/

 

发动机模型是设计师通过 3ds Max 建模,然后导出 obj 与 mtl 文件,在 HT 中解析 obj 与 mtl 文件生成 3D 场景中可用的模型(可参考 obj 手册《通过JSON加载》章节),因为各个部件需要单独操作,所以设备模型拆分为多个 obj 文件后导入。

2D 面板部分则是通过 HT 的矢量绘制,我们需要创建 ht.graph.GraphView 和 ht.graph3d.Graph3dView 来呈现 2D 和 3D 的内容。相关代码如下:

  1. var g2d = new ht.graph.GraphView();
  2. var g3d = new ht.graph3d.Graph3dView();
  3. // 将 3D 组件加入到 body 下
  4. g3d.addToDOM();
  5. // 将 2D 组件加入到 3D 组件的根 div 下
  6. g2d.addToDOM(g3d.getView());

  

当我们点击“展开”按钮时,给各个动画设置不同的延迟,使动画错开执行,以达到更好的视觉效果,让2D图纸和3D场景更好地联动起来。

 

如果我们的每个动画都匀速运行,那看起来难免有些单调。于是我给不同动画加上了不同的 Easing 函数,Easing 函数通过定义不同曲线的数据公式方式,来描述每一帧回调时需要改变图形参数属性的幅度,从而达到均匀、先快后慢、先慢后快,甚至先超出起始值和结束值再慢慢恢复的各种动画特效。这里还有个例子可以帮助我们更直观的感受不同 Easing 函数的效果:《From Easing》。

例如图纸中心的跟随部件拆解旋转放大的圆环,我给它设置了 Easing.backBoth 缓动效果,代码如下:

  1. // 圆环动画
  2. animCenter(data) {
  3. ht.Default.startAnim({
  4. duration: 4500,
  5. // 设置缓动函数
  6. easing: Easing.backBoth,
  7. // 延迟一秒执行动画
  8. delay: 1000,
  9. action: function (v, t) {
  10. // 修改图元缩放值
  11. data.setScale(1 + v * 0.9, 1 + v * 0.9);
  12. // 修改图元旋转角度
  13. data.setRotation(Math.PI * v);
  14. },
  15. });
  16. }
  17.  
  18. // 缓动函数
  19. Easing.easeOutStrong = function (t) {
  20. var BACK_CONST = 1.70158;
  21. if ((t *= 2) < 1) {
  22. return .5 * (t * t * (((BACK_CONST *= (1.525)) + 1) * t - BACK_CONST));
  23. }
  24. return .5 * ((t -= 2) * t * (((BACK_CONST *= (1.525)) + 1) * t + BACK_CONST) + 2);
  25. };

设备部件的拆解动画,是通过改变节点的坐标和旋转角度来实现的,代码如下:

  1. // targetP3 为拆解后的坐标,p3为当前坐标
  2. var p3 = node.p3();
  3. var offset = [targetP3[0] - p3[0], targetP3[1] - p3[1], targetP3[2] - p3[2]];
  4.  
  5. // targetR3 为拆解后的旋转角度,r3为当前旋转角度
  6. var r3 = node.r3();
  7. var offset = [targetR3[0] - r3[0], targetR3[1] - r3[1], targetR3[2] - r3[2]];
  8.  
  9. // 拆解动画
  10. ht.Default.startAnim({
  11. duration: 2000,
  12. // 设置缓动函数
  13. easing: Easing.easeOutStrong,
  14. delay: 1000,
  15. action: function (v, t) {
  16. // 修改节点坐标
  17. node.p3(p3[0] + offset[0] * v, p3[1] + offset[1] * v, p3[2] + offset[2] * v);
  18. // 修改节点旋转角度
  19. node.r3(r3[0] + offset[0] * v, r3[1] + offset[1] * v, r3[2] + offset[2] * v);
  20. },
  21. });
  22.  
  23. // 缓动函数
  24. Easing.easeOutStrong = function (t) {
  25. return 1 - (--t) * t * t * t;
  26. };

还有图纸两侧的面板,可以通过设置它的裁剪方向和裁剪比例实现隐藏效果,代码如下:

  1. // 设置图元裁剪方向为从右到左
  2. node.s(\'clip.direction\', \'left\');
  3.  
  4. // 裁剪动画
  5. ht.Default.startAnim({
  6. duration: 1800,
  7. easing: Easing.easeOutStrong,
  8. action: function (v, t) {
  9. // 修改图元裁剪比例
  10. node.s(\'clip.percentage\', 1 - v);
  11. }
  12. });
  13.  
  14. // 缓动函数
  15. Easing.easeOutStrong = function (t) {
  16. return 1 - (--t) * t * t * t;
  17. };

 

接下来我们实现视角变化动画来观察设备不同部件构造,3D 场景中的视角是由 Graph3dView 提供的 center(目标点坐标)和 eye(摄像机坐标)两个参数决定的,所以视角动画只要动态改变这两个参数,这里用了 HT 提供的 moveCamera 方法实现,代码如下:

  1. g3d.moveCamera([-466, 93, -280], [40, -40, -40], {
  2. duration: 2500,
  3. easing: function (t) {
  4. return 1 - (--t) * t * t * t;
  5. },
  6. });

设备中一些小的部件吸附在大部件上,会跟随大部件移动旋转。比如这个液压杆,当我们要实现小部件的运动动画时,如果用修改坐标的方式计算起来比较麻烦,所以我们用修改锚点的方式来实现,锚点影响着节点的位置,锚点也是旋转和缩放的中心点。这里通过修改液压杆的 Y 轴锚点实现动画,效果如下:

相关代码如下:

  1. ht.Default.startAnim({
  2. duration: 800,
  3. action: function (v, t) {
  4. // 修改节点 Y 轴锚点
  5. node.setAnchor3d(0.5,v,0.5);
  6. },
  7. };

  

 

点击流动按钮后,我们可以看到管道内有液体流动的动画。要实现流动效果,首先我们需要一张二方连续贴图(左右或上下可以无缝衔接的贴图),然后我们再通过代码驱动 UV 向 U 轴的正值方向偏移一个象限,并无限循环这一动作,效果如下:

 代码如下:

  1. ht.Default.startAnim({
  2. duration: 2000,
  3. action: function (v, t) {
  4. // 修改贴图uv值
  5. node.s(\'shape3d.uv.offset\', [v, 0]);
  6. },
  7. };

  

为了能透过外壳清楚的观察到设备内部结构,所以当鼠标悬停在部件上时,我调整了外壳模型透明度并设置模型高亮模式,相关代码如下:

  1. // 设置高亮颜色
  2. ht.Style[\'highlight.color\'] = \'rgba(255,255,255,0.6)\';
  3. // 设置当前高亮的模式
  4. g3d.setHighlightMode(\'mouseover\');
  5. // 节点启用高亮效果
  6. data.s(\'highlight.visible\', true);
  7.  
  8. // 节点设置为可交互
  9. data.s(\'interactive\', true);
  10. // 节点开启交互后,不阻止场景上默认的交互行为
  11. data.s(\'preventDefaultWhenInteractive\', false);
  12.  
  13. // 监听交互事件
  14. g3d.mi(function (e) {
  15. // 鼠标移入事件
  16. if (e.kind === \'onEnter\') {
  17. // 节点开启透明
  18. data.s(\'shape3d.transparent\', true);
  19. // 设置节点透明度
  20. data.s(\'shape3d.opacity\', 0.25);
  21. }
  22.  
  23. // 鼠标移出事件
  24. if (e.kind === \'onLeave\') {
  25. data.s(\'shape3d.transparent\', false);
  26. }
  27. });

  

最后,我们再对整个场景的视角范围做下限制,代码如下:

  1. // 设置最大角度
  2. ht.Default.graph3dViewMaxPhi = Math.PI / 2;
  3. // 设置最小角度
  4. ht.Default.graph3dViewMinPhi = Math.PI / 4;

  

    通过案例我们可以感受到,相较于传统方式,设备的三维展示具有更灵活的表现形式和更直观生动的效果,对于出口型企业,生动的演示动画能让外商更快了解产品的工作原理和优势,还能避免因语言误差而造成误解。而且比起普通的工业动画,Web 上的可视化系统展示内容更丰富、自由度更高,后续需求更改也更为灵活、成本更低。

    本文使用的设备模型是设计师虚构的核动力发动机,更注重于模型的展示效果,如果应用于实际产品中,还可以制作更还原实际的设备拆解流程,通过线上的 3D 产品操作演练,对工作人员进行产品组装、拆分、维修培训。有兴趣可以参考我们另一个案例《基于 HTML5 WebGL + WebVR 的 3D 虚拟现实可视化培训系统》。

原文地址:https://www.cnblogs.com/xhload3d/p/12520693.html

版权声明:本文为htdaydayup原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/htdaydayup/p/12264003.html