Reputation: 330
I am trying to use projectPoint
to get the 2D information of the updated SCNNode in scenekit and save them.
Based on ignotusverum's suggestion, I am able to save the SCNNode in to a path in a button.
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)
}
Started saving via a start button:
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()})
}
Saved them via a stop button clicks:
@IBAction private func stopPressed() {
do {
fpsTimer.invalidate() //turn off the timer
let capturedData = captureData.map{$0.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")
}
}
So far works fine with the points being saved. The problem is that in the saved data, I realized the data is only saving one frame of the x and y vertices. For example:
[(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)
The data is repeating with one frame rather than the period I want to save from the moment when I click start button to stop button.
My question is how to save the updated SCNNode over time from the moment when I click start button to stop button?
Thanks in advance!
Upvotes: 2
Views: 437
Reputation: 559
If I understand your question correctly you want to save the vertex positions each time they are updated, keeping track of all previous updates as well as the most recent one. In order to do this you simply need to append the new vertex position array to the global array with saved data.
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
}
Upvotes: 1
Reputation: 1213
SceneKit calls this method exactly once per frame. If you do stuff inside the renderer, you gotta "get it done" and get out, otherwise it can have an impact on FPS.
If you need to move or check a lot of loop stuff, you can use timers to perform those efforts separately and that allows you some control over it. You can still keep your FPS up and break loops up or chunk work in the timers. If you do this, just make sure you put timers in the main thread.
You might also look at: node.presentation, ie: properties reflect the transitory values determined by any in-flight animations currently affecting the node.
Upvotes: 1