(ARKit 2 Room Scanner) 如何使用 UIBezierPath 和 featurePoints 通过 ARKit 2 和 ARWorldMap 创建一个具有周围环境几何形状的节点
(ARKit 2 Room Scanner) How to use UIBezierPath & featurePoints to create a node with the geometry of your surroundings with ARKit 2 & ARWorldMap
我正在使用 ARKit 2 和 ARWorldMapData 我创建了一个 AR 世界,它可以使用来自 link here 的地图数据等识别您的周围环境。现在我想弄清楚如何获取所有特征点并连接然后创建我的 surroundings/ARWorldMap 的网格(以前从未尝试过我认为是 ARKit 2)。虽然我确信您可以通过将特征点与 UIBezierPath 连接来实现它。这样您就可以使用路径创建的形状作为您的节点几何体。
经过测试,以下代码不会在屏幕上产生任何内容,或者至少我看不到它。所以现在这就是问题所在。虽然我确定这可能会有更多问题。
我几乎只是用这个问题中的例子here看看它是否可以远程工作。
代码:
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
guard !(anchor is ARPlaneAnchor) else { return }
let testNode = bezierNode.clone()
DispatchQueue.main.async {
node.addChildNode(testNode)
}
}
func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
// take the current frame/views features points and create an array out of them
guard let currentFrame = self.sceneView.session.currentFrame,
let featurePointsArray = currentFrame.rawFeaturePoints?.points else { return }
// Create STROKE BezierPath
let strokeBezierPath = UIBezierPath()
strokeBezierPath.lineWidth = 0.1
// Start the BezierPath at the first feature points on the screen
strokeBezierPath.move(to: CGPoint(x: CGFloat(featurePointsArray.first!.x), y: CGFloat(featurePointsArray.first!.y)))
// iterate through all feature pints and add then to the path
featurePointsArray.forEach { (pointLocation) in
strokeBezierPath.addLine(to: CGPoint(x: CGFloat(pointLocation.x), y: CGFloat(pointLocation.y)))
}
// Close the Stroke BezierPath
strokeBezierPath.close()
// Do fancy work, not sure what this does
let cgPath = strokeBezierPath.cgPath.copy(
strokingWithWidth: strokeBezierPath.lineWidth,
lineCap: strokeBezierPath.lineCapStyle,
lineJoin: strokeBezierPath.lineJoinStyle,
miterLimit: strokeBezierPath.miterLimit)
// Create the actually bezierpath that were going to use to create the nodes geometry
let bezierPath = UIBezierPath(cgPath: cgPath)
let shape = SCNShape(path: bezierPath, extrusionDepth: 0.1)
shape.firstMaterial?.diffuse.contents = UIColor.blue
let node = SCNNode(geometry: shape)
// Add newly created node to the reference that gets passed to the didAdd delegate
bezierNode = node
// Then anchor gets added when we touch the screen with a tap gesture temporary that call the didAdd delegate
}
所以它几乎可以占用这样的房间并填充 walls/points 创建网格:
结果看起来像这样,但显然是真人大小和实际站在房间里的视角:
如果有任何天才可以帮助重构我的代码,请提供比这更好的代码,或者知道如何实际实现它。那太棒了!。谢谢
ARWorldMap 可以存储特征点,但对您来说更有趣的是,它还会保存 ARPlaneAnchors,这些本质上是已经为您构建的网格。结果不会是完美的,但更接近您想要实现的目标并且更容易。我以前做过这个,并在推特上展示了一个视频,在公园里展示一个视觉 ARWorldMap,每次你在那个位置启动应用程序时,它都会扩展(改进)。 ARKit 可以从特征点检测平面,数学已经为你完成,所以使用它而不是试图 link 特征点在一起。
https://twitter.com/londonrom/status/1010150386848628736
我正在使用 ARKit 2 和 ARWorldMapData 我创建了一个 AR 世界,它可以使用来自 link here 的地图数据等识别您的周围环境。现在我想弄清楚如何获取所有特征点并连接然后创建我的 surroundings/ARWorldMap 的网格(以前从未尝试过我认为是 ARKit 2)。虽然我确信您可以通过将特征点与 UIBezierPath 连接来实现它。这样您就可以使用路径创建的形状作为您的节点几何体。
经过测试,以下代码不会在屏幕上产生任何内容,或者至少我看不到它。所以现在这就是问题所在。虽然我确定这可能会有更多问题。
我几乎只是用这个问题中的例子here看看它是否可以远程工作。
代码:
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
guard !(anchor is ARPlaneAnchor) else { return }
let testNode = bezierNode.clone()
DispatchQueue.main.async {
node.addChildNode(testNode)
}
}
func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
// take the current frame/views features points and create an array out of them
guard let currentFrame = self.sceneView.session.currentFrame,
let featurePointsArray = currentFrame.rawFeaturePoints?.points else { return }
// Create STROKE BezierPath
let strokeBezierPath = UIBezierPath()
strokeBezierPath.lineWidth = 0.1
// Start the BezierPath at the first feature points on the screen
strokeBezierPath.move(to: CGPoint(x: CGFloat(featurePointsArray.first!.x), y: CGFloat(featurePointsArray.first!.y)))
// iterate through all feature pints and add then to the path
featurePointsArray.forEach { (pointLocation) in
strokeBezierPath.addLine(to: CGPoint(x: CGFloat(pointLocation.x), y: CGFloat(pointLocation.y)))
}
// Close the Stroke BezierPath
strokeBezierPath.close()
// Do fancy work, not sure what this does
let cgPath = strokeBezierPath.cgPath.copy(
strokingWithWidth: strokeBezierPath.lineWidth,
lineCap: strokeBezierPath.lineCapStyle,
lineJoin: strokeBezierPath.lineJoinStyle,
miterLimit: strokeBezierPath.miterLimit)
// Create the actually bezierpath that were going to use to create the nodes geometry
let bezierPath = UIBezierPath(cgPath: cgPath)
let shape = SCNShape(path: bezierPath, extrusionDepth: 0.1)
shape.firstMaterial?.diffuse.contents = UIColor.blue
let node = SCNNode(geometry: shape)
// Add newly created node to the reference that gets passed to the didAdd delegate
bezierNode = node
// Then anchor gets added when we touch the screen with a tap gesture temporary that call the didAdd delegate
}
所以它几乎可以占用这样的房间并填充 walls/points 创建网格:
结果看起来像这样,但显然是真人大小和实际站在房间里的视角:
如果有任何天才可以帮助重构我的代码,请提供比这更好的代码,或者知道如何实际实现它。那太棒了!。谢谢
ARWorldMap 可以存储特征点,但对您来说更有趣的是,它还会保存 ARPlaneAnchors,这些本质上是已经为您构建的网格。结果不会是完美的,但更接近您想要实现的目标并且更容易。我以前做过这个,并在推特上展示了一个视频,在公园里展示一个视觉 ARWorldMap,每次你在那个位置启动应用程序时,它都会扩展(改进)。 ARKit 可以从特征点检测平面,数学已经为你完成,所以使用它而不是试图 link 特征点在一起。 https://twitter.com/londonrom/status/1010150386848628736