我正在尝试使用Swift的ARKit制作一个简单的测量应用程序。
我运行了一个演示项目来找到一个很好的例子。
但是我不能使用'SphereNode'。
使用Swift创建第一个应用程序的过程具有挑战性。
我希望您能理解,因为英语不是我的母语。
我的完整消息如下。
谢谢。
P.S。我的系统版本为'OSX ver。 10.14','xCode版本。 10.0'最新的日期为2018. 09. 27
//
// ViewController.swift
// Reference : https://virtualrealitypop.com/ios-11-tutorial-how-to-measure-objects-with-arkit-743d2ec78afc.
//
import UIKit
//Import ARKit and SceneKit frameworks
import ARKit
import SceneKit
//Conform our ViewController to ARSCNViewDelegate protocol.
class ViewController: UIViewController, ARSCNViewDelegate {
var nodes: [SphereNode] = []
//Create a lazy sceneView variable to store ARSCNView instance
lazy var sceneView: ARSCNView = {
let view = ARSCNView(frame: CGRect.zero)
view.delegate = self
return view
}()
//Create a label to display status information.
lazy var infoLabel: UILabel = {
let label = UILabel(frame: CGRect.zero)
label.font = UIFont.preferredFont(forTextStyle: UIFont.TextStyle.title1)
label.textAlignment = .center
label.backgroundColor = .white
return label
}()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
//Add sceneView to our host view
view.addSubview(sceneView)
//Add the label to host view
view.addSubview(infoLabel)
//
let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTap))
tapRecognizer.numberOfTapsRequired = 1
sceneView.addGestureRecognizer(tapRecognizer)
}
@objc func handleTap(sender: UITapGestureRecognizer) {
//2
let tapLocation = sender.location(in: sceneView)
//3
let hitTestResults = sceneView.hitTest(tapLocation, types: .featurePoint)
if let result = hitTestResults.first {
//4
let position = SCNVector3.positionFrom(matrix: result.worldTransform)
//5
let sphere = SphereNode(position: position)
//6
sceneView.scene.rootNode.addChildNode(sphere)
let lastNode = nodes.last
nodes.append(sphere)
if lastNode != nil {
//7
let distance = lastNode!.position.distance(to: sphere.position)
infoLabel.text = String(format: "Distance: %.2f meters", distance)
}
}
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
//Resize sceneView
sceneView.frame = view.bounds
//Update the label position
infoLabel.frame = CGRect(x: 0, y: 16, width: view.bounds.width, height: 64)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
//Start ARKit session
let configuration = ARWorldTrackingConfiguration()
sceneView.session.run(configuration, options: [.resetTracking, .removeExistingAnchors])
}
func session(_ session: ARSession, cameraDidChangeTrackingState camera: ARCamera) {
//Implement protocol function to display status changes
var status = "Loading..."
switch camera.trackingState {
case ARCamera.TrackingState.notAvailable:
status = "Not available"
case ARCamera.TrackingState.limited(_):
status = "Analyzing..."
case ARCamera.TrackingState.normal:
status = "Ready"
}
infoLabel.text = status
}
}
extension SCNVector3 {
func distance(to destination: SCNVector3) -> CGFloat {
let dx = destination.x - x
let dy = destination.y - y
let dz = destination.z - z
return CGFloat(sqrt(dx*dx + dy*dy + dz*dz))
}
static func positionFrom(matrix: matrix_float4x4) -> SCNVector3 {
let column = matrix.columns.3
return SCNVector3(column.x, column.y, column.z)
}
}
答案 0 :(得分:0)
您缺少定义SphereNode
的代码。
您可以使用以下内容替换该行:
let sphereGeometry = SCNSphere(radius: 0.1)
let sphere = SCNNode(geometry: sphereGeometry)
sphere.position = position
答案 1 :(得分:0)
您的问题的答案很简单。您正在引用名为Subclass
的SCNNode SphereNode
,但这未包含在您的项目中。
快速查看问题中提供的源代码参考会指向以下GitHub Repositor
y:AR Measure Demo
如果您在源代码中查找,则它们是名为SphereNode.swift
的类:
//
// SphereNode.swift
// ArMeasureDemo
//
// Created by Igor K on 8/17/17.
// Copyright © 2017 Igor K. All rights reserved.
//
import SceneKit
class SphereNode: SCNNode {
init(position: SCNVector3) {
super.init()
let sphereGeometry = SCNSphere(radius: 0.005)
let material = SCNMaterial()
material.diffuse.contents = UIColor.red
material.lightingModel = .physicallyBased
sphereGeometry.materials = [material]
self.geometry = sphereGeometry
self.position = position
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
这样,如果您使当前文件类似,错误就会消失:
import UIKit
class SphereNode: SCNNode {
init(position: SCNVector3) {
super.init()
let sphereGeometry = SCNSphere(radius: 0.005)
let material = SCNMaterial()
material.diffuse.contents = UIColor.red
material.lightingModel = .physicallyBased
sphereGeometry.materials = [material]
self.geometry = sphereGeometry
self.position = position
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
//Import ARKit and SceneKit frameworks
import ARKit
import SceneKit
//Conform our ViewController to ARSCNViewDelegate protocol.
class ViewController: UIViewController, ARSCNViewDelegate {
var nodes: [SphereNode] = []
//Create a lazy sceneView variable to store ARSCNView instance
lazy var sceneView: ARSCNView = {
let view = ARSCNView(frame: CGRect.zero)
view.delegate = self
return view
}()
//Create a label to display status information.
lazy var infoLabel: UILabel = {
let label = UILabel(frame: CGRect.zero)
label.font = UIFont.preferredFont(forTextStyle: UIFont.TextStyle.title1)
label.textAlignment = .center
label.backgroundColor = .white
return label
}()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
//Add sceneView to our host view
view.addSubview(sceneView)
//Add the label to host view
view.addSubview(infoLabel)
//
let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTap))
tapRecognizer.numberOfTapsRequired = 1
sceneView.addGestureRecognizer(tapRecognizer)
}
@objc func handleTap(sender: UITapGestureRecognizer) {
//2
let tapLocation = sender.location(in: sceneView)
//3
let hitTestResults = sceneView.hitTest(tapLocation, types: .featurePoint)
if let result = hitTestResults.first {
//4
let position = SCNVector3.positionFrom(matrix: result.worldTransform)
//5
let sphere = SphereNode(position: position)
//6
sceneView.scene.rootNode.addChildNode(sphere)
let lastNode = nodes.last
nodes.append(sphere)
if lastNode != nil {
//7
let distance = lastNode!.position.distance(to: sphere.position)
infoLabel.text = String(format: "Distance: %.2f meters", distance)
}
}
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
//Resize sceneView
sceneView.frame = view.bounds
//Update the label position
infoLabel.frame = CGRect(x: 0, y: 16, width: view.bounds.width, height: 64)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
//Start ARKit session
let configuration = ARWorldTrackingConfiguration()
sceneView.session.run(configuration, options: [.resetTracking, .removeExistingAnchors])
}
func session(_ session: ARSession, cameraDidChangeTrackingState camera: ARCamera) {
//Implement protocol function to display status changes
var status = "Loading..."
switch camera.trackingState {
case ARCamera.TrackingState.notAvailable:
status = "Not available"
case ARCamera.TrackingState.limited(_):
status = "Analyzing..."
case ARCamera.TrackingState.normal:
status = "Ready"
}
infoLabel.text = status
}
}
extension SCNVector3 {
func distance(to destination: SCNVector3) -> CGFloat {
let dx = destination.x - x
let dy = destination.y - y
let dz = destination.z - z
return CGFloat(sqrt(dx*dx + dy*dy + dz*dz))
}
static func positionFrom(matrix: matrix_float4x4) -> SCNVector3 {
let column = matrix.columns.3
return SCNVector3(column.x, column.y, column.z)
}
}
希望有帮助...