swift - generate a specific number of SCNPlane [Swift, ARkit]
问题描述
I am beginner in swift and ARkit, and I want to generate a specific number of SCNPlane, let say 10 for example. I tried with multiple way but I only get one SCNPlane.
What do I need to do to place multiple SCNPlane in the code without any overlapping between them?
Here my code section:
//
// MarkViewController.swift
// Jawwab
//
// Created by Nora Almunaif on 26/05/1440 AH.
// Copyright © 1440 atheer. All rights reserved.
//
import UIKit
import SceneKit
import ARKit
class MarkViewController: UIViewController {
@IBOutlet weak var sceneView: ARSCNView!
lazy var bookNode: SCNNode = {
let text = SCNText(string: "only for testing", extrusionDepth: 1)
let material = SCNMaterial()
material.diffuse.contents = UIColor.black
text.materials = [material]
let node = SCNNode()
node.position = SCNVector3(0, 0, 0)
node.scale = SCNVector3(0.0009, 0.0009, 0.0009)
node.geometry = text
let minVec = node.boundingBox.min
let maxVec = node.boundingBox.max
let bound = SCNVector3Make(maxVec.x - minVec.x,
maxVec.y - minVec.y,
maxVec.z - minVec.z);
let plane = SCNPlane(width: CGFloat(bound.x + 25),
height: CGFloat(bound.y + 8))
plane.cornerRadius = 5
plane.firstMaterial?.diffuse.contents = UIColor.gray.withAlphaComponent(0.8)
let planeNode = SCNNode(geometry: plane)
planeNode.position = SCNVector3(CGFloat( minVec.x - 10) + CGFloat(bound.x) / 2 ,
CGFloat( minVec.y) + CGFloat(bound.y) / 2,CGFloat(minVec.z - 0.01))
node.addChildNode(planeNode)
planeNode.name = "text"
return node
}()
override func viewDidLoad() {
super.viewDidLoad()
self.sceneView.delegate = self as? ARSCNViewDelegate
sceneView.showsStatistics = true
self.configureLighting()
}
func configureLighting() {
sceneView.autoenablesDefaultLighting = true
sceneView.automaticallyUpdatesLighting = true
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
resetTrackingConfiguration()
}
func resetTrackingConfiguration() {
guard let referenceImages = ARReferenceImage.referenceImages(inGroupNamed: "AR Resources", bundle: nil)
else {
print("No image detected");
return }
let configuration = ARWorldTrackingConfiguration()
configuration.detectionImages = referenceImages
let options: ARSession.RunOptions = [.resetTracking, .removeExistingAnchors]
sceneView.session.run(configuration, options: options)
// label.text = "Move camera around to detect images"
}
}
@available(iOS 12.0, *)
extension MarkViewController: ARSCNViewDelegate {
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
DispatchQueue.main.async {
guard let imageAnchor = anchor as? ARImageAnchor,
let imageName = imageAnchor.referenceImage.name else { return }
var i=0
while i<5 {
let overlayNode = self.getNode(withImageName: imageName)
let minVec = overlayNode.boundingBox.min
let maxVec = overlayNode.boundingBox.max
let bound = SCNVector3Make(maxVec.x - minVec.x,
maxVec.y - minVec.y,
maxVec.z - minVec.z);
let plane = SCNPlane(width: CGFloat(bound.x),
height: CGFloat(bound.y))
plane.cornerRadius = 5
plane.firstMaterial?.diffuse.contents = UIColor.gray.withAlphaComponent(0.8)
let planeNode = SCNNode(geometry: plane)
planeNode.position = SCNVector3(CGFloat( minVec.x - 10) + CGFloat(bound.x) / 2 ,
CGFloat( minVec.y) + CGFloat(bound.y) / 2,CGFloat(minVec.z - 0.01))
let image = UIImage(named: "flag")
planeNode.geometry?.firstMaterial?.diffuse.contents = image
planeNode.name = "text"
self.sceneView.scene.rootNode.addChildNode(overlayNode)
self.sceneView.autoenablesDefaultLighting = true
i = i + 1
}
}
}
func getPlaneNode(withReferenceImage image: ARReferenceImage) -> SCNNode {
let plane = SCNPlane(width: image.physicalSize.width,
height: image.physicalSize.height)
let node = SCNNode(geometry: plane)
return node
}
func getNode(withImageName name: String) -> SCNNode {
var node = SCNNode()
switch name {
case "Book":
node = bookNode
default:
break
}
return node
}
}
And thank you
.....................................
解决方案
您正在调用 DidAdd Node(for:Anchor:) ,每个图像锚点只会调用一次。查看您的代码,您在完全相同的位置创建了 5 次完全相同的几何图形,因此看起来只有一个。尝试根据从 0 到 5 的 i 更改位置。
planeNode.position = SCNVector3(CGFloat( minVec.x - 10) + CGFloat(bound.x) / 2 , CGFloat( minVec.y) + CGFloat(bound.y) + i / 2,CGFloat(minVec.z - 0.01))
飞机现在应该堆叠在一起。
推荐阅读
- python - 带有 numba 和 @guvectorize 的“签名中的错误令牌”
- postgresql - 通过运行 ANALYZE 来提高查询性能?
- ios - 如何在自定义视图中创建更改属性的修饰符
- swift - SwiftUI Simple ForEach 多次报错不符合View
- python - Python Pip 未将包安装到虚拟环境 Visual Studio for Mac 中的正确目录中 - “未解决的导入”
- javascript - Rxjs - 如何在 combinelatest 之后调用两个 httpService?
- python - 在 Python 中编写 Discord 机器人 - 如何使机器人将命令限制到某个服务器?
- visual-studio - 调试找不到着陆页
- python - 如何将字符串类型列表更改为列表类型,然后删除 nan 元素
- javascript - 当该字段是外键时,如何使用 OR 条件进行查询