基於 HTML5 WebGL 的垃圾分類系統

来源:https://www.cnblogs.com/xhload3d/archive/2019/10/08/11633965.html
-Advertisement-
Play Games

垃圾分類,一般是指按一定規定或標准將垃圾分類儲存、分類投放和分類搬運,從而轉變成公共資源的一系列活動的總稱。分類的目的是提高垃圾的資源價值和經濟價值,力爭物盡其用。垃圾在分類儲存階段屬於公眾的私有品,垃圾經公眾分類投放後成為公眾所在小區或社區的區域性準公共資源,垃圾分類搬運到垃圾集中點或轉運站後成... ...


前言

垃圾分類,一般是指按一定規定或標准將垃圾分類儲存、分類投放和分類搬運,從而轉變成公共資源的一系列活動的總稱。分類的目的是提高垃圾的資源價值和經濟價值,力爭物盡其用。垃圾在分類儲存階段屬於公眾的私有品,垃圾經公眾分類投放後成為公眾所在小區或社區的區域性準公共資源,垃圾分類搬運到垃圾集中點或轉運站後成為沒有排除性的公共資源。從國內外各城市對生活垃圾分類的方法來看,大致都是根據垃圾的成分、產生量,結合本地垃圾的資源利用和處理方式來進行分類的。到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

在工業物聯網從嬰兒走到青年的成熟道路上,一定會有更多的潛力和挑戰在等著我們,等待我們去開發,等待我們去創造!相信我們的技術成為國際水準會指日可待!同時在十一國慶後的第一個工作日祝大家精神飽滿,工作順利!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 寫在前面 在真正的前端開發中,我們很少去寫行內樣式和內嵌樣式,通常都是去引用外部樣式。 而在我們學習之初的外部樣式表都是用link引入的,但是當後來我們學習的逐漸深入,發現@import也可以引入樣式。那麼同樣是引入外部樣式,這兩者有什麼區別呢,下麵請跟隨我來詳細瞭解一下link和@import的區 ...
  • 1、我們先設置兩個盒子大小,顏色等等,然後定位重疊在一起,最後再進行動畫設置 例子如下: 2、效果如下: 恢復內容結束 ...
  • 一、屬性的認識 :link 表示滑鼠點擊之前,也稱為原始狀態; :visited 表示滑鼠點擊之後狀態; :hover 表示滑鼠懸停狀態; :active 表示滑鼠點擊狀態; L-V-H-A LV愛 HA恨 二、例子 運行結果是: 1、初始,未訪問狀態 2、滑鼠懸停時狀態 3、點擊是狀態 4、點擊之 ...
  • 大家好!先上圖看看本次案例的整體效果。 實現思路: 實現步驟如下: store: 以上就是大轉盤抽獎核心步驟的整體思路,歡迎討論。 Vue.js實戰之游戲抽獎系列全集 ↓↓↓↓↓↓↓↓↓↓↓ 【Vue.js實戰案例】- Vue.js實現老虎-機抽獎總結 【Vue.js實戰案例】- Vue.js實現九 ...
  • 參考:https://blog.csdn.net/xxjmlgb/article/details/49467717 ...
  • 解構:ES6允許按照一定模式,從數組和對象中提取值,對變數進行賦值。 對象的解構與數組有一個重要的不同。數組的元素是按次序排列的,變數的取值由他的位置決定;而對象的屬性沒有次序,變數必須與屬性同名,才能取到正確的值。 變數解構賦值的用途:交換變數的值,從函數返回多個值,函數參數的定義,提取JSON數 ...
  • Let:用來聲明變數,但是所聲明的變數,只在let命令所在的代碼塊內生效。 變數提升:變數可以在聲明之前使用,值為undefined。 暫時性死區:在代碼塊內,使用let命令聲明變數之前,該變數都是不可用的。 不允許重覆聲明:let不允許在相同作用域內,重覆聲明同一變數。 Const:const聲明 ...
  • 本文僅限於入門級,沒有成規模製作,希望能對你有所幫助。 因為在開發多個項目中可能會用到同一個組件,那麼我們通過複製粘貼的形式更新,無異於是笨拙的,我們可以通過上傳到npm後,不斷迭代npm包來實現更新。 前期準備 初始化project 這裡我們使用 來初始化一個vue項目。 or 首先我們來開發一個 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...