Swift:使用scenekit中的projectPoint随时间获取并保存更新的SCNNode
Swift: Obtain and save the updated SCNNode over time using projectPoint in scenekit
我正在尝试使用projectPoint
获取scenekit中更新后的SCNNode的二维信息并保存。
根据 ignotusverum 的建议,我可以将 SCNNode 保存到按钮中的路径中。
var lastPosition: CGPoint?
func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
guard anchor == currentFaceAnchor,
let contentNode = selectedContentController.contentNode,
contentNode.parent == node
else { return }
for (index, vertex) in vertices.enumerated() {
let vertex = sceneView.projectPoint(node.convertPosition(SCNVector3(vertex), to: nil))
let xVertex = CGFloat(vertex.x)
let yVertex = CGFloat(vertex.y)
Position = CGPoint(x: xVertex, y: yVertex)
}
selectedContentController.session = sceneView?.session
selectedContentController.sceneView = sceneView
selectedContentController.renderer(renderer, didUpdate: contentNode, for: anchor)
}
通过开始按钮开始保存:
private var fpsTimer = Timer()
private var currentCaptureFrame = 0
@IBAction private func startPressed() {
currentCaptureFrame = 0 //inital capture frame
fpsTimer = Timer.scheduledTimer(withTimeInterval: 1/fps, repeats: true, block: {(timer) -> Void in self.recordData()})
}
通过单击停止按钮保存它们:
@IBAction private func stopPressed() {
do {
fpsTimer.invalidate() //turn off the timer
let capturedData = captureData.map{[=13=].stringRepresentation}.joined(separator:"\(lastPosition)>")
let dir: URL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last! as URL
let url = dir.appendingPathComponent("testing.txt")
try capturedData.appendLineToURL(fileURL: url as URL)
}
catch {
print("Could not write to file")
}
}
到目前为止,保存的点数工作正常。问题是在保存的数据中,我意识到数据只保存了 x 和 y 顶点的一帧。例如:
[(411.0618591308594, 534.4215087890625), (410.7286071777344, 544.9381713867188), (411.5425720214844, 522.1063232421875), (412.0340881347656, 512.1854248046875),...
[(411.0618591308594, 534.4215087890625), (410.7286071777344, 544.9381713867188), (411.5425720214844, 522.1063232421875), (412.0340881347656, 512.1854248046875)
从单击开始按钮到停止按钮的那一刻起,数据以一帧重复,而不是我要保存的周期。
我的问题是如何保存从我点击开始按钮到停止按钮那一刻起随时间更新的 SCNNode?
提前致谢!
SceneKit 每帧只调用一次此方法。如果您在渲染器中执行操作,则必须“完成它”然后退出,否则会对 FPS 产生影响。
如果您需要移动或检查大量循环内容,您可以使用计时器分别执行这些工作,这样您就可以对其进行一些控制。你仍然可以保持你的 FPS 并打破循环或在计时器中分块工作。如果这样做,请确保将计时器放在主线程中。
您还可以查看:node.presentation,即:属性反映由当前影响节点的任何 in-flight 动画确定的临时值。
如果我对你的问题的理解正确,你想在每次更新时保存顶点位置,跟踪所有以前的更新以及最近的更新。为此,您只需将新的顶点位置数组附加到包含已保存数据的全局数组即可。
var savedPositions = [CGPoint]()
var beginSaving = false
func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
guard anchor == currentFaceAnchor,
let contentNode = selectedContentController.contentNode,
contentNode.parent == node
else { return }
for vertex in vertices {
let projectedPoint = sceneView.projectPoint(node.convertPosition(SCNVector3(vertex), to: nil))
if beginSaving {
savedPositions.append(CGPoint(x: projectedPoint.x, y: projectedPoint.y))
}
}
selectedContentController.session = sceneView?.session
selectedContentController.sceneView = sceneView
selectedContentController.renderer(renderer, didUpdate: contentNode, for: anchor)
}
@IBAction private func startPressed() {
beginSaving = true
}
@IBAction private func stopPressed() {
beginSaving = false
....//do whatever with your array of saved positions
}
我正在尝试使用projectPoint
获取scenekit中更新后的SCNNode的二维信息并保存。
根据 ignotusverum 的建议,我可以将 SCNNode 保存到按钮中的路径中。
var lastPosition: CGPoint?
func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
guard anchor == currentFaceAnchor,
let contentNode = selectedContentController.contentNode,
contentNode.parent == node
else { return }
for (index, vertex) in vertices.enumerated() {
let vertex = sceneView.projectPoint(node.convertPosition(SCNVector3(vertex), to: nil))
let xVertex = CGFloat(vertex.x)
let yVertex = CGFloat(vertex.y)
Position = CGPoint(x: xVertex, y: yVertex)
}
selectedContentController.session = sceneView?.session
selectedContentController.sceneView = sceneView
selectedContentController.renderer(renderer, didUpdate: contentNode, for: anchor)
}
通过开始按钮开始保存:
private var fpsTimer = Timer()
private var currentCaptureFrame = 0
@IBAction private func startPressed() {
currentCaptureFrame = 0 //inital capture frame
fpsTimer = Timer.scheduledTimer(withTimeInterval: 1/fps, repeats: true, block: {(timer) -> Void in self.recordData()})
}
通过单击停止按钮保存它们:
@IBAction private func stopPressed() {
do {
fpsTimer.invalidate() //turn off the timer
let capturedData = captureData.map{[=13=].stringRepresentation}.joined(separator:"\(lastPosition)>")
let dir: URL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last! as URL
let url = dir.appendingPathComponent("testing.txt")
try capturedData.appendLineToURL(fileURL: url as URL)
}
catch {
print("Could not write to file")
}
}
到目前为止,保存的点数工作正常。问题是在保存的数据中,我意识到数据只保存了 x 和 y 顶点的一帧。例如:
[(411.0618591308594, 534.4215087890625), (410.7286071777344, 544.9381713867188), (411.5425720214844, 522.1063232421875), (412.0340881347656, 512.1854248046875),...
[(411.0618591308594, 534.4215087890625), (410.7286071777344, 544.9381713867188), (411.5425720214844, 522.1063232421875), (412.0340881347656, 512.1854248046875)
从单击开始按钮到停止按钮的那一刻起,数据以一帧重复,而不是我要保存的周期。
我的问题是如何保存从我点击开始按钮到停止按钮那一刻起随时间更新的 SCNNode?
提前致谢!
SceneKit 每帧只调用一次此方法。如果您在渲染器中执行操作,则必须“完成它”然后退出,否则会对 FPS 产生影响。
如果您需要移动或检查大量循环内容,您可以使用计时器分别执行这些工作,这样您就可以对其进行一些控制。你仍然可以保持你的 FPS 并打破循环或在计时器中分块工作。如果这样做,请确保将计时器放在主线程中。
您还可以查看:node.presentation,即:属性反映由当前影响节点的任何 in-flight 动画确定的临时值。
如果我对你的问题的理解正确,你想在每次更新时保存顶点位置,跟踪所有以前的更新以及最近的更新。为此,您只需将新的顶点位置数组附加到包含已保存数据的全局数组即可。
var savedPositions = [CGPoint]()
var beginSaving = false
func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
guard anchor == currentFaceAnchor,
let contentNode = selectedContentController.contentNode,
contentNode.parent == node
else { return }
for vertex in vertices {
let projectedPoint = sceneView.projectPoint(node.convertPosition(SCNVector3(vertex), to: nil))
if beginSaving {
savedPositions.append(CGPoint(x: projectedPoint.x, y: projectedPoint.y))
}
}
selectedContentController.session = sceneView?.session
selectedContentController.sceneView = sceneView
selectedContentController.renderer(renderer, didUpdate: contentNode, for: anchor)
}
@IBAction private func startPressed() {
beginSaving = true
}
@IBAction private func stopPressed() {
beginSaving = false
....//do whatever with your array of saved positions
}