# 主程式結構-林彥廷 **強烈建議先看完潛在問題再繼續閱讀此部分** ---Part I--- 基本上最初始的架構是根據其他專案的結構來布置的 參照`https://www.geeksforgeeks.org/how-to-build-a-simple-augmented-reality-android-app/` 根據教學,最後可以完成一「手動調整物件大小和方向之AR程式」 *注意事項 由於Sceneform已經開源,參照架構已經將Sceneform直接引入專案中,可能需要做些微調整(架設期間並未碰到BUG,碰到的話依據原專案進行修正) 而接下來開始進行自動化部分調整。 首先,AR物件和地理座標系統並不能共用,即讀取到指北針方位也無法套用在AR物件上(也可能可以,但製作時並未找到方法)好在錨定物件時是可以截取其姿勢的,所以架設的錨點必須採用指定的方向,該方向由設計者決定,故設計路線時就必須考慮到如何下錨。 ---Part II--- WIP Anchor AnchorNode Pose(可能用不到) setLookDirection(決定AR物件的指向,同時還要決定物體的「頂端」是哪一邊,預設狀態應該以足夠應付所有可能)。 中間曾經做出錯誤的狀態,是讓箭頭直接指到指向點,而不是擷取指向點的方位套回箭頭上,也許用在錯誤導正有用。 ---Part II--- 此部分講述如何把專案架起來 ![](https://i.imgur.com/4zlEyKB.png) 48行載入相機和其相關數據,照寫即可 ![](https://i.imgur.com/vvxcCsg.png) 53-63行為欲使用之參數設定,具體用途後面會提到。 ![](https://i.imgur.com/5wC8ODc.png) 126和127非常重要,126是用來承接雲錨ID用的,最簡單暴力的做法就是一個ID配一個``Anchor``,所以要用幾個給幾個 127行的``AnchorNode``用來跟場景對接,具體是在Sceneform上,對接上了才可以對物件進行任何動作。 基本上也是照著寫即可。 ![](https://i.imgur.com/MPwC7QR.png) 149~158是存放ID的陣列,每個預先打好的錨點都有一個ID以便存取,為了操作方便則必須把它存在程式中,若覺得太長可以嘗試``shortcode``去縮短ID。 ![](https://i.imgur.com/QbtNdWy.png) 163行決定下拉選單選到哪個目的地。 ![](https://i.imgur.com/L32ZAaD.png) 173行是計算並記住使用者在開始導航後,會經過哪些雲錨。 ![](https://i.imgur.com/EeDVMdt.png) 196~218也是參數設定。 比較重要的是``navigate_point``,用來承接使用者起點;`Destination_in_floyd`是承接目標點用的。 ![](https://i.imgur.com/2gsGBmO.png) 222~242是檢查系統是否支援AR繪製用的,在最一開始的教學裡有這一段,照著寫即可。 ![](https://i.imgur.com/oJqtpuD.png) 243~247行是全部的可能狀態,這個只會用在設定雲錨時,照寫即可。 ![](https://i.imgur.com/xz0B4Eq.png) 249行這個``Anchor``是用在打雲錨時,不是用來存取雲錨時,請特別注意。 ![](https://i.imgur.com/abDAsEq.png) 254~255是雲錨的一些起始參數,254是指現在雲錨還未設定,255是自行加入的參數,用於後續給導航使用時判定的。 ![](https://i.imgur.com/TXui4kQ.png) 263~288是給下拉式選單內的選項,263行式第一個下拉區,選擇樓層,274~288是第二下拉區,會根據第一下拉區決定顯示其中的哪一個陣列,在從該陣列中選擇要去的目的地。這樣寫的用意在於不會讓使用者的下拉選單過長。 ![](https://i.imgur.com/DrMwfBX.png) 327~362是佛洛伊德演算中需要用到的關係矩陣,搜尋佛洛伊德演算法就有很多介紹影片,簡單理解為每個雲錨跟每個雲錨之間的關係即可,舉例來說,若有15個不同的雲錨,則產生``n*(n-1)-n,n=15``個關係,若是可直接通到的點關係為1,反之則為1000,此時看到第333行,1號點可以直接通到0號點和2號點,其餘則無法直通。這些關係就是後續路徑規劃和計算時的依據,因此請再三確認關係正確性。 另,364和366是用於承載計算和計算結果用的。 ![](https://i.imgur.com/M8jrsM3.png) 371開始進入程式的初始階段,375跟376可以不寫(是用來測試的,實際上沒有用到)373設定畫面使用哪個xml檔,374用於連結畫面上的按鈕已用於擷取或是傳遞動作(如按下按鈕要做什麼) 379是計算每個點到任意點的最短路徑 ![](https://i.imgur.com/JCTAsob.png) 圖為計算函式的內容,請務必先理解原理再開始修改。 要修改的部分其實也只有m、n、i和j要小於多少而已 回到381和382,這裡是連結畫面上的下拉選單,以便擷取使用者選擇的項目。 ![](https://i.imgur.com/vRUgGkG.png) 402~677都是關於下拉選單的細項,也可以上網搜尋下拉選單怎麼寫,我的結構可能有點亂。邏輯上來說選完第一個(樓層)後才選下一個 ![](https://i.imgur.com/l4n7qGM.png) ``pos``就是選到第一下拉選單的哪一個,依據這個再決定下一個下拉選單顯示哪一些選項。 ``onItemSelected``用於擷取選了哪個項目,注意是第二個下拉選單。 ![](https://i.imgur.com/mNqCKDi.png) 683是確定裝置可以使用AR的繪製,一旦符合就會繼續執行 686用於確定相機畫面擷取 687是要點下螢幕後才會觸發的一連串動作,而這裡面包含的行動便是放置錨點,這個錨點在693就成為雲錨;694改變錨點狀態為已創建 696是為雲錨創建一個AR物件,以利於在開發時可以看到雲錨結合AR物件後的方向 ![](https://i.imgur.com/YekB9W4.png) 這裡的結構後續還會出現(在778行的時候會有解釋) ![](https://i.imgur.com/T72ZMDq.png) 702這行是一個固定寫法,擷取每一畫格的畫面,用於協調AR物件和使用者的一些距離或方向改變時物體該怎麼變化(這也是為什麼採用Sceneform而非OpenGL原生繪製,因為這部分簡化許多) 707行擷取錨點狀態 713標明若是成功HOST,則會有ID顯示在畫面上 ![](https://i.imgur.com/K8ySbY7.png) 727行就是按下開始導航後會執行的動作 741~745行開始比較重要,這裡開始要1個``Anchor``對1個``AnchorNode``,且一個``Anchor``對應一個雲錨ID ![](https://i.imgur.com/4IkezHb.png) 這裡的target就是前面下拉選單選取的目標,依據不同的目標,將其對應至佛洛伊德演算的關係矩陣中的不同雲錨。 ![](https://i.imgur.com/ZwuOQ1l.png) 778行,這串中間的``R.raw.arrow``是要渲染的物件,這個物件必須自己去找,免費素材很多(我是在這找的https://clara.io/),自己畫也行但不推薦。 到786行就照打。接著看到782行的pointer函式 ![](https://i.imgur.com/G44UfYJ.png) 1249行,``pointer``承接``node``和``modelRenderable``,``modelRenderable``這個照著寫就好,重點在``node``上,``node``承接了包括調整方向、調整物件大小和獲取其三維向量值。 1252和1255行是將``node``接上場景和執行渲染 789~1142是導航的部分 ![](https://i.imgur.com/s97yS7C.png) 首先,793~805是用來檢測起點的(go要小於的數字應該為總錨點數),與每個錨點比較後取得相似度較高的那個錨點(此時``cloudanchorhost[go].getCloudAnchorState() == Anchor.CloudAnchorState.SUCCESS ``就會成立,且尋找起點的動作就會因為S7的改變而不再執行) ![](https://i.imgur.com/yoUchVs.png) 807~828規畫路徑部分 有了起點和終點,現在要透過佛洛伊德演算的路徑表去得出最短路徑並讓使用者按照該路徑前進,``navigate``函式便是要做這件事情,而計算出的路徑會存入``path``這個陣列。 ![](https://i.imgur.com/ABsnvmy.png) 839確定了路徑點上的雲錨ID成功存取並且還沒到最後一個點之前,都會進去這個區間 851則是確定若是到達路徑上最後一點(即目的地),那就顯示訊息提醒使用者已抵達 ![](https://i.imgur.com/rMUDohS.png) 862~884都是提示訊息的設定(可以關閉提示訊息視窗或是回到主頁面),可以照著寫,也可以去搜尋網路上其他人的做法 ![](https://i.imgur.com/pESPTuo.png) 903表示若下一導航點已經偵測到就進入並執行內部行動 904是將導航點繪製在原先打入的地方 906是擷取雲錨的姿勢用的 918是擷取相機姿勢用的(相當於我們現在看出去的方向就是在這裡取得) 919是將相機跟AR物件的高度調成一樣,以便我們後續的應用。 920計算相機和AR物件的向量差,會用在畫面上指引使用者應該往哪邊前進 923是將向量轉為角度(簡單理解,具體的原理牽涉的篇幅較大,若想深入在自行搜尋),轉為角度後才能在同一平面上讓使用者知道往哪走才是對的 ![](https://i.imgur.com/juqGb3U.png) 933~937是把導航用的箭頭固定在畫面中間用的 933擷取畫面中的資訊 934是計算面中心點,1080和1920是螢幕的長寬,根據不同裝置應該要有不同的數據。 935是設定這個導航物件要距離鏡頭多遠(也就影響使用者實際上看見的物體有多大) 936將鏡頭前的導航物件``node1``的相對位置放在距離鏡頭1m的位置 937就是設定導航指向需要轉多少度,但我們不必知道,套上函式交給程式計算即可。 ![](https://i.imgur.com/mv8Va3B.png) 991~1012具體在更新使用者現在到哪個點了 993的迴圈檢測畫面中是否出現了導航路徑上的下個點,若有則將當前導航點設定為它並將其方位套入畫面上的導航指標 1004的判斷會在尚未到達最後一個導航點(即目的地)時不斷將u更改為當前偵測到的導航點並擷取該導航點的指向給使用者看(即一直顯示在螢幕上的箭頭),若u與目的地相等則停止導航。