千炮捕鱼游戏下载|街机千炮捕鱼1破解版
 找回密碼
 注冊帳號

掃一掃,訪問微社區

AR醬 ARKit從入門到精通(3)--平面檢測

4
回復
510
查看
打印 上一主題 下一主題
[ 復制鏈接 ]
排名
2299
昨日變化

34

主題

262

帖子

1514

積分

Rank: 9Rank: 9Rank: 9

UID
156756
好友
11
蠻牛幣
998
威望
0
注冊時間
2016-7-13
在線時間
527 小時
最后登錄
2019-12-2

專欄作家

馬上注冊,結交更多好友,享用更多功能,讓你輕松玩轉社區。

您需要 登錄 才可以下載或查看,沒有帳號?注冊帳號

x
本帖最后由 geekli 于 2019-10-21 21:02 編輯

本部分主要通過ARKit實現平面檢測并在其上面放置一個虛擬物體。

效果預覽:



在正式開始前,我們需要了解“Horizontal Plane”這一概念。當我們在ARKit中討論水平面時,我們究竟在討論什么呢?當我們在ARKit中檢測到一個水平面時,我們在技術上檢測到的其實是一個ARPlaneAnchor。那么什么是ARPlaneAnchor呢?ARPlaneAnchor大體上可以理解為一個包含檢測到的水平面信息的對象(水平與位置信息)。

本部分主要介紹Horizontal Plane的實現方式,所以我們直接在這個工程(鏈接: https://pan.baidu.com/s/1eJeIbkzk1OUy_YLk6X3yog 提取碼: vv6y )上面繼續開發,對于如何在Xcode使用ARKit實現AR效果不懂的可以查看之前的文章:

下載完后在Xcode打開,并運行項目,如下圖所示:



Step 1: 水平面檢測

在ViewController的setUpSceneView()方法中添加以下內容:

[AppleScript] 純文本查看 復制代碼
configuration.planeDetection = .horizontal


通過將ARWorldTrackingConfiguration的planeDetection屬性設置為.horizontal,這告訴ARKit去查找任何水平面。一旦ARKit檢測到一個水平面,該水平面將被添加到sceneView的session中。

為了檢測水平面,必須采用ARSCNViewDelegate協議。在ViewController類下面,創建一個ViewController類擴展來實現協議:
[AppleScript] 純文本查看 復制代碼
extension ViewController: ARSCNViewDelegate {

}


在類擴展的內部,實現renderer(_:didAdd:for:)方法:
[AppleScript] 純文本查看 復制代碼
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {

}

每當場景視圖的session添加了一個新的ARAnchor時,就會調用這個協議方法。ARAnchor是表示三維空間中物理位置和方向的對象。稍后我們將使用ARAnchor來檢測水平面。

將sceneView的委托分配給setUpSceneView()中的ViewController。

還可以設置sceneView的調試選項來顯示現實環境中的特征點。這可以幫助找到一個特征點足夠多的水平面。一旦檢測到足夠的特征點來識別水平表面,就會調用renderer(_:didAdd:for:)。

目前setUpSceneView()方法應該是這樣的:
[AppleScript] 純文本查看 復制代碼
func setUpSceneView() {
    let configuration = ARWorldTrackingConfiguration()
    configuration.planeDetection = .horizontal
    
    sceneView.session.run(configuration)
    
    sceneView.delegate = self
    sceneView.debugOptions = [ARSCNDebugOptions.showFeaturePoints]
}

更新renderer(_:didAdd:for:)方法:
[AppleScript] 純文本查看 復制代碼
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
    // 1
    guard let planeAnchor = anchor as? ARPlaneAnchor else { return }
    
    // 2
    let width = CGFloat(planeAnchor.extent.x)
    let height = CGFloat(planeAnchor.extent.z)
    let plane = SCNPlane(width: width, height: height)
    
    // 3
    plane.materials.first?.diffuse.contents = UIColor.transparentLightBlue
    
    // 4
    let planeNode = SCNNode(geometry: plane)
    
    // 5
    let x = CGFloat(planeAnchor.center.x)
    let y = CGFloat(planeAnchor.center.y)
    let z = CGFloat(planeAnchor.center.z)
    planeNode.position = SCNVector3(x,y,z)
    planeNode.eulerAngles.x = -.pi / 2
    
    // 6
    node.addChildNode(planeNode)
}

創建一個SCNPlane來可視化ARPlaneAnchor。SCNPlane是一個矩形的“單邊”平面幾何。我們獲取未包裝的ARPlaneAnchor區段的x和z屬性,并使用它們創建一個SCNPlane。
使用剛剛創建的SCNPlane幾何圖形初始化一個SCNNode。
初始化x、y和z常量來表示planeAnchor的中心x、y和z位置。這是我們的planeNode的位置。
最后,將planeNode作為子節點添加到新添加的SceneKit節點上。

然后Build項目,效果如下圖:

隨著ARKit接收到關于我們的環境的額外信息,我們需要擴展之前檢測到的水平面,以利用更大的表面,或者用新的環境信息更準確地表示,實現方法renderer(_:didUpdate:for:):
[AppleScript] 純文本查看 復制代碼
func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {

}

每次更新SceneKit節點的屬性以匹配其對應的錨(anchor)時,都會調用此方法。

node參數為我們提供了錨的更新位置。錨參數給出了更新后的寬度和高度。有了這兩個參數,我們可以更新之前實現的SCNPlane,用更新后的寬度和高度反映新的位置。

接下來,在renderer(_:didUpdate:for:)中添加以下代碼:
[AppleScript] 純文本查看 復制代碼
// 1
guard let planeAnchor = anchor as?  ARPlaneAnchor,
    let planeNode = node.childNodes.first,
    let plane = planeNode.geometry as? SCNPlane
    else { return }

// 2
let width = CGFloat(planeAnchor.extent.x)
let height = CGFloat(planeAnchor.extent.z)
plane.width = width
plane.height = height

// 3
let x = CGFloat(planeAnchor.center.x)
let y = CGFloat(planeAnchor.center.y)
let z = CGFloat(planeAnchor.center.z)
planeNode.position = SCNVector3(x, y, z)

Build應用,實現效果如下圖:


Step 2: 添加3D物體

在本部分教程剛開始的時候下載的project包含了一個3D物體(ship)。
在ViewController類中插入以下方法,將船放置在水平面的頂部:
[AppleScript] 純文本查看 復制代碼
@objc func addShipToSceneView(withGestureRecognizer recognizer: UIGestureRecognizer) {
    let tapLocation = recognizer.location(in: sceneView)
    let hitTestResults = sceneView.hitTest(tapLocation, types: .existingPlaneUsingExtent)
    
    guard let hitTestResult = hitTestResults.first else { return }
    let translation = hitTestResult.worldTransform.translation
    let x = translation.x
    let y = translation.y
    let z = translation.z
    
    guard let shipScene = SCNScene(named: "ship.scn"),
        let shipNode = shipScene.rootNode.childNode(withName: "ship", recursively: false)
        else { return }
    
    
    shipNode.position = SCNVector3(x,y,z)
    sceneView.scene.rootNode.addChildNode(shipNode)
}

對于這部分內容不熟悉的可以查看之前的文章:
這里與之前唯一的區別是,我們在types參數中傳遞了一個不同的參數來檢測sceneView中現有的平面錨。
[AppleScript] 純文本查看 復制代碼
func addTapGestureToSceneView() {
    let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(ViewController.addShipToSceneView(withGestureRecognizer:)))
    sceneView.addGestureRecognizer(tapGestureRecognizer)
}

該方法將向sceneView添加一個tap手勢識別器。

對于頂部的cherry,調用viewDidLoad()內部方法,向sceneView添加一個tap手勢識別器:
[AppleScript] 純文本查看 復制代碼
addTapGestureToSceneView()

現在運行,你應該能夠檢測到一個可視化的水平面,然后上面會放置一個小船,你可以任意角度查看它。效果如下圖:


可以通過取消viewDidLoad()內部的configureLighting()注釋來啟用照明。該功能非常簡單,用兩行代碼來啟用照明:
[AppleScript] 純文本查看 復制代碼
sceneView.autoenablesDefaultLighting = true
sceneView.automaticallyUpdatesLighting = true


完整項目鏈接:https://github.com/appcoda/ARKitHorizontalPlaneDemo
參考鏈接:https://www.appcoda.com/arkit-horizontal-plane/


------AR Portal(AR開發者社區)整理
關注微信公眾號:AR開發者社區(國內領先的AR開發者交流學習社區和AR內容平臺

回復

使用道具 舉報

排名
2299
昨日變化

34

主題

262

帖子

1514

積分

Rank: 9Rank: 9Rank: 9

UID
156756
好友
11
蠻牛幣
998
威望
0
注冊時間
2016-7-13
在線時間
527 小時
最后登錄
2019-12-2

專欄作家

沙發
樓主 2019-10-21 21:02:35 只看該作者
更多開發干貨,可以關注微信公眾號:AR開發者社區
回復 支持 反對

使用道具 舉報

5熟悉之中
777/1000
排名
4594
昨日變化

1

主題

89

帖子

777

積分

Rank: 5Rank: 5

UID
56032
好友
2
蠻牛幣
1707
威望
0
注冊時間
2014-11-18
在線時間
367 小時
最后登錄
2019-12-15
板凳
2019-10-25 14:31:21 只看該作者
這個說基于什么引擎開發的呀,unity ARKit 怎么下架了,在Asset Store 上搜索不到了
回復 支持 反對

使用道具 舉報

排名
64939
昨日變化

0

主題

11

帖子

16

積分

Rank: 1

UID
169072
好友
0
蠻牛幣
22
威望
0
注冊時間
2016-9-18
在線時間
3 小時
最后登錄
2019-12-4
地板
2019-11-28 16:39:53 只看該作者
謝謝分享!!!!!!!
回復

使用道具 舉報

0

主題

12

帖子

14

積分

Rank: 1

UID
337346
好友
0
蠻牛幣
5
威望
0
注冊時間
2019-12-7
在線時間
2 小時
最后登錄
2019-12-8
5#
2019-12-7 11:54:13 只看該作者
謝謝分享!!
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 注冊帳號

本版積分規則

千炮捕鱼游戏下载 揭阳福彩投注站微信交流 极速时时彩是假的吗 美人捕鱼赢钱技巧 重庆快乐10分玩法 老k棋牌能提现吗 双色球2017119华仔蓝球 cf真人游戏生化视频 老k棋牌骗局电玩 国外星级酒店为什么赚钱 香港一诗两码中特