引言
最近在學習AR.js相關的知識,希望通過AR.js在web端實現AR(Augmented Reality)的應用。AR.js的網上教程較少,相對比較全的資料是官網的一個文檔(AR.js文檔,好像要FQ才能訪問,目前沒看到中文版本)。
熟悉AR.js的同學應該都知道,AR.js基於三種方式展示AR內容:
1)Image Tracking 2)Location Based AR 3)Marker Tracking
Marker Tracking是最常見的基於maker的AR顯示方式,我今天要講的是我學習使用Image Tracking的方式展示AR內容時,遇到的問題,以及解決方案。(這里就不詳細介紹這三種的細節,大家可以到查看AR.js文檔)
關鍵詞:AR.js A-Frame Image Tracking nft url配置
Image Tracking簡介
Image Tracking顧名思義,就是基於一張圖片去展示AR內容,其實原理和基於Marker Tracking類似,都是根據圖片的特性點識別圖片並跟蹤。AR.js集成了A-Frame和three.js兩個框架,基於這兩個框架都能實現Image Tracking。
圖片要求
用於做Image Tracking的圖片有一定要求,原則上圖片越精細越好。推薦使用300dpi及以上的圖片,72dpi的圖片勉強可以,但是AR展示設備必須靠的很近,而且必須保持靜止。
生成圖片對應的Image Descriptors
AR.js官方提供了web工具,可以將圖片轉換成Image Descriptors,AR.js其實是根據生成的Image Descriptors做圖片識別和跟蹤定位的。
根據圖片生成的Image Descriptors包含三個文件,分別為以.fset, .fset3, .iset為后綴名的文件。假設你生成的Image Descriptors文件名為:demo.fset, demo.fset3, demo.iset,那么你的Image Descriptors名字為demo(去除后綴名)。
官方Demo嘗試
官方提供的基於A-Frame框架的Image Tracking例子,關鍵html代碼如下:
藍色線畫出的分別是Image Descriptors文件所在URL路徑(即nft url路徑),和gltf格式3D模型的URL路徑。Image Descriptors URL最后的trex為Image Descriptors的名字。
PS:測試運行官方demo非常順利,只是有些慢,畢竟官方demo文件資源都是在國外服務器上。
部署自有web服務
部署官方demo到自有web服務器上,將以上藍色划線的URL替換成自有的Image Descriptors路徑和gltf格式的3D模型路徑。
發現只替換gltf-model是可以的,但是替換掉nft的url之后,則demo運行失敗,界面一直卡在
經過調試console的報錯信息為:Error in loading marker on Worker 404。
確認是Image Descriptors文件加載失敗,Image Descriptors文件URL訪問失敗導致。
問題定位
查看AR.js加載Image Descriptors文件源代碼(aframe-ar-nft.js文件),發現Image Descriptors加載函數如下:
var onLoad = function () { ar = new ARController(msg.pw, msg.ph, param); var cameraMatrix = ar.getCameraMatrix(); // after the ARController is set up, we load the NFT Marker var regexM = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#()?&//=]*)/igm var reM = regexM.test(msg.marker); if (reM == true) { console.log('msg.marker=', msg.marker); nftMarkerUrl = msg.marker; } else if (reM == false) { console.log('basePath=', basePath); nftMarkerUrl = basePath + '/' + msg.marker; } console.log('nftMarkerUrl=', nftMarkerUrl); ar.loadNFTMarker(nftMarkerUrl, function (markerId) { ar.trackNFTMarkerId(markerId); postMessage({ type: 'endLoading' }) }, function (err) { console.log('Error in loading marker on Worker', err) });
從源代碼可以看出,如果我們指定nft的URL是以域名方式提供的,如官方demo的https://arjs-cors-proxy.herok...,則直接使用我們傳入的URL;
否則,使用basePath + 我們傳入的URL(msg.marker變量即為我們傳入的URL)。
如果加載出錯,則會使用console.log('Error in loading marker on Worker', err)打印出錯信息。
調試程序發現,由於我部署的服務是localhost的:http://localhost:8088/test
,或者http://127.0.0.1:8088/test
非域名方式,所以走的是basePath + 我們傳入的URL分支,打印出來的調試結果如下:
從打印結果看出,basepath值為http://127.0.0.1:8088而不是http://127.0.0.1:8088/test(test為我部署的web服務名稱),導致拼接的ntf的URL路徑錯誤。
問題解決方案
修改nft的URL如下圖所示:
問題結論
AR.js(實際上是A-Frame)在處理nft的url和model url上存在差異,正確配置方式有如下兩種:
1)html部署的web服務必須支持使用域名訪問,且必須將ntf的url配置成Image Descriptors文件所在的完整的域名訪問路徑;
2)html部署的是本地web服務,采用127.0.0.1或者服務IP地址訪問,則ntf和model的URL路徑必須配置成相對路徑,如上圖所示。且nft的路徑必須包含web服務名稱,而modle的url路徑則不包含web服務名稱。
PS:感覺A-Frame這塊處理的不是很合理,畢竟不是每個人一上來就有域名的服務器。在本地部署AR相關web應用(web服務只能用IP訪問),而nft的url配置行為和model的url配置行為不一致,很容易導致錯誤。
model url配置更合理,支持絕對路徑http://127.0.0.1:8088/test/trex/scene.gltf配置和相對路徑trex/scene.gltf配置,無需指定web服務名稱。