前言

垃圾分类,一般是指按一定规定或标准将垃圾分类储存、分类投放和分类搬运,从而转变成公共资源的一系列活动的总称。分类的目的是提高垃圾的资源价值和经济价值,力争物尽其用。垃圾在分类储存阶段属于公众的私有品,垃圾经公众分类投放后成为公众所在小区或社区的区域性准公共资源,垃圾分类搬运到垃圾集中点或转运站后成为没有排除性的公共资源。从国内外各城市对生活垃圾分类的方法来看,大致都是根据垃圾的成分、产生量,结合本地垃圾的资源利用和处理方式来进行分类的。到2019年6月25日,生活垃圾分类制度将入法。一套应用于工业物联网的智能一体化的垃圾分类机械臂将随之而来,由此,我应用 HT for Web  的图型化编辑工具打造了一款形象生动的例子:Garbage classification,也借此机会与大家一起分享和学习。

代码实现

(注:gif 的上传大小有限,实际效果与还请参考 demo 链接)

首先,我应用已经精心布置好的 3D 场景,为了有更好的操作体验感,我们要从它的基本设置开始:

gv.setMovableFunc(() => { return false }) // 禁止拖动
gv.getWireframe = (d) => { d.s('wf.visible', false) } // 隐藏选中边框
gv.setEye([583, -212, -789]) // 设置眼睛
gv.setCenter([-76, -654, -133]) // 设置中心点
gv.setFar(100000) // 设置远端位置
gv.setNear(10) // 设置近端位置
gv.setInteractors([ new ht.graph3d.MapInteractor(gv) ]) // 设置交互限制
gv.setSkyBox(dm.getDataByTag('skyBox')) // 设置天空球
window.document.oncontextmenu = () => { return false } // 全局设置右键菜单禁用
gv.scene = { // 复制初始位置
eye: ht.Default.clone(gv.getEye()),
center: ht.Default.clone(gv.getCenter()),
far: ht.Default.clone(gv.getFar()),
near: ht.Default.clone(gv.getNear()),
}

我复制了一下整个场景的初始视角情况方便我做稍后的处理,我监听了部分鼠标事件来形成自己的操作风格(比如双击背景还原视角以及双击模型拉近视角):

gv.mi(e => {
let data = e.data
let kind = e.kind
if (kind === 'doubleClickBackground') { // 双击背景
gv.moveCamera(this.gv.scene.eye, this.gv.scene.center, {duration : 1000}) // 恢复视角
}
else if (kind === 'doubleClickData') { // 双击模型
gv.flyTo(data, {animation : {duration : 500}, distance : 800}) // 拉近视角
}
})

好了,准备工作做好了,下面来实现动画部分,除了了解 垃圾分类 的方式外我还参考了网上很多机械臂的视频,学习它的运动模式和动作细节,对每个结构和部位的动画进行步骤的排序和构思。这里我挑选几处动画的实现方式来展示:

function mechanicalArmAnim1() {
  ht.Default.startAnim({
    duration: 1000,
    easing: (t) => { return t },
    action: (v, t) => {
      postbrachium.r3(degrees(0) + (degrees(20) - degrees(0)) * v, postbrachium.r3()[1], postbrachium.r3()[2]) // 后臂向下移
    },
    finishFunc: () => {
      setTimeout(() => {
        mechanicalArmAnim2()
      }, 300)
    }
  })
}
function mechanicalArmAnim2() {
  ht.Default.startAnim({
    duration: 1000,
    easing: (t) => { return t },
    action: (v, t) => {
      postbrachium.p3(-208 + (-184 + 208) * v, postbrachium.p3()[1], postbrachium.p3()[2]) // 后臂前伸
      hydraulicRod1.r3(degrees(0) + (degrees(8) - degrees(0)) * v, hydraulicRod1.r3()[1], hydraulicRod1.r3()[2]) // 液压杆1倾斜
      extensionRod1.r3(degrees(0) + (degrees(8) - degrees(0)) * v, extensionRod1.r3()[1], extensionRod1.r3()[2]) // 伸长杆1倾斜
      extensionRod1.p3(-169 + (-185 + 169) * v, -516 + (-511 + 516) * v, extensionRod1.p3()[2]) // 伸长杆1伸长
      hydraulicRod2.r3(degrees(0) + (degrees(-8) - degrees(0)) * v, hydraulicRod2.r3()[1], hydraulicRod2.r3()[2]) // 液压杆2倾斜
      extensionRod2.r3(degrees(0) + (degrees(-8) - degrees(0)) * v, extensionRod2.r3()[1], extensionRod2.r3()[2]) // 伸长杆2倾斜
      extensionRod2.p3(-169 + (-185 + 169) * v, -516 + (-511 + 516) * v, extensionRod2.p3()[2]) // 伸长杆2伸长
    },
    finishFunc: () => {
      setTimeout(() => {
        mechanicalArmAnim3()
      }, 300)
    }
  })
}
function mechanicalArmAnim3() {
  let oldValue = antebrachium.r3()[0]
  ht.Default.startAnim({
    duration: 1000,
    easing: (t) => { return t },
    action: (v, t) => {
      hydraulicRod1.r3(degrees(8) + (degrees(7) - degrees(8)) * v, hydraulicRod1.r3()[1], hydraulicRod1.r3()[2]) // 液压杆1倾斜
      extensionRod1.r3(degrees(8) + (degrees(7) - degrees(8)) * v, extensionRod1.r3()[1], extensionRod1.r3()[2]) // 伸长杆1倾斜
      extensionRod1.p3(-185 + (-186 + 185) * v, -511 + (-507 + 511) * v, extensionRod1.p3()[2]) // 伸长杆1伸长
      hydraulicRod2.r3(degrees(-8) + (degrees(-7) - degrees(-8)) * v, hydraulicRod2.r3()[1], hydraulicRod2.r3()[2]) // 液压杆2倾斜
      extensionRod2.r3(degrees(-8) + (degrees(-7) - degrees(-8)) * v, extensionRod2.r3()[1], extensionRod2.r3()[2]) // 伸长杆2倾斜
      extensionRod2.p3(-185 + (-186 + 185) * v, -511 + (-507 + 511) * v, extensionRod2.p3()[2]) // 伸长杆2伸长
      postbrachium.r3(degrees(20) + (degrees(25) - degrees(20)) * v, postbrachium.r3()[1], postbrachium.r3()[2]) // 后臂向下移
      antebrachium.r3(oldValue + (degrees(-40) - oldValue) * v, antebrachium.r3()[1], antebrachium.r3()[2]) // 前臂向下移
      claw1.r3(degrees(-20) + (degrees(-60) - degrees(-20)) * v, claw1.r3()[1], claw1.r3()[2]) // 上爪抓取
      claw2.r3(degrees(-60) + (degrees(-30) - degrees(-60)) * v, claw2.r3()[1], claw2.r3()[2]) // 下爪抓取
    },
    finishFunc: () => {
      mechanicalArmAnim4()
    }
  })
}

这一段动画是机械臂从初始化状态到向下抓取的一个过程,我将每段动画分成函数来写比较方便后续管理,每一处也代表了一个步骤。这其中最复杂且细微的步骤要数液压杆的运动了,为了让动画看起来更加真实,我除了将手臂单独运动的过程中加入了延时执行下一段动画以体现机器运动的特点外,也把液压杆的部分也做了动画,如果不做处理,那么机械臂在上下移动的时候就会有不科学的效果出现。动画函数 在这种 demo 中应用的最广,而且里面也包含了一些缓动函数,有兴趣的博友们可以 点此处 自己亲自动手玩一玩~

这里面的拾取垃圾步骤还应用了我过去介绍过的 吸附 功能,这个方法非常的适合抓取物体的动作,通过 setHost 使节点吸附于宿主,这样就相当于子节点跟随父节点移动,此时只需要对机械臂进行偏移和旋转的操作,垃圾便会随之一起运动了,大大减少了工作量!

还有一部分更酷的属性设置给大家展示一下,可以让 3D 场景整体有更真实的阴影处理效果。首先我们要注意将无关的节点阴影通过 node.s('shadow.cast', false) 关闭,比如编组用的box,背景,地板和面板等。

最后我们就把阴影的细节做下调整,达到比较好的效果:

gv.enableShadow(true, {
  degreeX : 0, // 投影 x 轴角度
  degreeZ : -25, // 投影 z 轴角度
  intensity : 0.3, // 阴影强度, 1 为黑色
  quality : 'high', // low / medium / high / ultra / 4096数值, 质量
  type : 'soft', // none / hard / soft
  radius : 0.2, // type 为 hard / soft 时,补充的边缘厚度,用来提供更柔和的边缘
  bias : -0.003 // 深度浮点偏差补足
})

总结

更多动画 demo 以及工业化领域的文章请继续关注我的博客,感谢大家的支持!

医疗站(https://www.cnblogs.com/htdaydayup/p/11558748.html

在工业物联网从婴儿走到青年的成熟道路上,一定会有更多的潜力和挑战在等着我们,等待我们去开发,等待我们去创造!相信我们的技术成为国际水准会指日可待!同时在十一国庆后的第一个工作日祝大家精神饱满,工作顺利!

基于 HTML5 + WebGL 实现的垃圾分类系统的更多相关文章

  1. 基于 HTML5 + WebGL 实现 3D 挖掘机系统

    前言 在工业互联网以及物联网的影响下,人们对于机械的管理,机械的可视化,机械的操作可视化提出了更高的要求.如何在一个系统中完整的显示机械的运行情况,机械的运行轨迹,或者机械的机械动作显得尤为的重要,因 ...

  2. 基于 HTML5 WebGL 的楼宇智能化集成系统(一)

    前言       随着现代通信技术.计算机技术.控制技术的飞速发展,智能建筑已经成为现代建筑发展的主流.智能建筑是以建筑物为平台,兼备信息设施系统.信息化应用系统.建筑设备管理系统.公共安全系统等.集 ...

  3. 基于 HTML5 WebGL 的 CPU 监控系统

    前言 科技改变生活,科技的发展带来了生活方式的巨大改变.随着通信技术的不断演进,5G 技术应运而生,随时随地万物互联的时代已经来临.5G 技术不仅带来了更快的连接速度和前所未有的用户体验,也为制造业, ...

  4. 基于 HTML5 WebGL 的楼宇智能化集成系统(二)

    前言       一套完整的可视化操作交互上,必不可少 2D/3D 的融合,在上期我们介绍了有关 3D 场景的环视漫游.巡视漫游以及动画效果,还包括了冷站场景.热站场景以及智慧末端的实现原理,本期主要 ...

  5. 基于 HTML5 WebGL 的医疗物流系统

    前言 物联网( IoT ),简单的理解就是物体之间通过互联网进行链接.世界上的万事万物,都可以通过数据的改变进行智能化管理.ioT 的兴起在医疗行业中具有拯救生命的潜在作用.不断的收集用户信息并且实时 ...

  6. HTML5 + WebGL 实现的垃圾分类系统

    前言 垃圾分类,一般是指按一定规定或标准将垃圾分类储存.分类投放和分类搬运,从而转变成公共资源的一系列活动的总称.分类的目的是提高垃圾的资源价值和经济价值,力争物尽其用.垃圾在分类储存阶段属于公众的私 ...

  7. 基于 HTML5 + WebGL 的 3D 太阳系系统

    前言 近年来随着引力波的发现.黑洞照片的拍摄.火星上存在水的证据发现等科学上的突破,以及文学影视作品中诸如<三体>.<流浪地球>.<星际穿越>等的传播普及,宇宙空间 ...

  8. 基于 HTML5 WebGL 的楼宇智能化集成系统(三)

    前言       2018年7月,信息化部印发了<工业互联网平台建设及推广指南>和<工业互联网平台评价方法>,掀起了 工业互联网 的浪潮,并成为热词写入了报告中.同为信息发展下 ...

  9. 基于 HTML5 WebGL 的地铁站 3D 可视化系统

    前言 工业互联网,物联网,可视化等名词在我们现在信息化的大背景下已经是耳熟能详,日常生活的交通,出行,吃穿等可能都可以用信息化的方式来为我们表达,在传统的可视化监控领域,一般都是基于 Web SCAD ...

随机推荐

  1. 括号匹配(c语言实现)

    ⭐ 我的网站: www.mengyingjie.com ⭐ 1要求 编写程序检查该字符串的括号是否成对出现,而且不能交叉出现. 输入: 一个字符串,里边可能包含"()"." ...

  2. 转:LinkedHashMap和HashMap的比较使用

    import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.uti ...

  3. 转:ext的xtype值

    基本组件: xtype Class 描述 button Ext.Button 按钮 splitbutton Ext.SplitButton 带下拉菜单的按钮 cycle Ext.CycleButton ...

  4. WordPress 文章目录插件 Easy Table of Contents 配置教程

    今天介绍一款目录插件,本站已经使用一段时间,感觉不错,实现效果可以看文章页右侧边栏有目录,点击目录内容会快速定位.推荐给大家. 一.安装Easy Table of Contents 插件主页搜索Eas ...

  5. Django序列化&django REST framework

    第一章.Django序列化操作 1.django的view实现商品列表页(基于View类) # 通过json来序列化,但手写字典key代码量较大,容易出错:还有遇到时间,图片序列化会报错 from g ...

  6. python-电脑结构、网络基础、单位转换

    目录 一.计算机五大部件 二.程序运行的过程 三.ARP协议 四.单位转换 一.计算机五大部件 电脑之父——冯·诺伊曼提出了计算机的五大部件:输入设备.输出设备.存储器.运算器和控制器. 我们把键盘和 ...

  7. 每个人都要学的图片压缩终极奥义,有效解决 Android 程序 OOM

    # 由来 在我们编写 Android 程序的时候,几乎永远逃避不了图片压缩的难题.除了应用图标之外,我们所要显示的图片基本上只有两个来源: 来自网络下载 本地相册中加载 不管是网上下载下来的也好,还是 ...

  8. java虚拟机体系分析

      一.JVM的生命周期: 1)程序开始执行,他就运行,程序停止,它就结束.有几个程序在执行,就有几个虚拟机在工作.只要Java虚拟机中还有普通的线程在执行,Java虚拟机就不会停止. 2)Java虚 ...

  9. Linux系列之yum安装

    yum是Linux系统的安装必备神器,简直不要太方便.但是新系统一般是不自带yum工具的,所以需要手动安装一下. 环境:centos7 新建一个目录用来保存yum安装包 mkdir install 进 ...

  10. 使用 .NET Core 3.0 的 AssemblyLoadContext 实现插件热加载

    一般情况下,一个 .NET 程序集加载到程序中以后,它的类型信息以及原生代码等数据会一直保留在内存中,.NET 运行时无法回收它们,如果我们要实现插件热加载 (例如 Razor 或 Aspx 模版的热 ...