My objective is to generate a SCNNode in the middle of another SCNNode that contains a SCNPlane.
The SCNPlane is generated in a renderer function like this:
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
guard let planeAnchor = anchor as? ARPlaneAnchor else { return }
let width = CGFloat(planeAnchor.extent.x)
let height = CGFloat(planeAnchor.extent.z)
let plane = SCNPlane(width: width, height: height)
plane.materials.first?.diffuse.contents = UIColor.orange
let planeNode = SCNNode(geometry: plane)
let x = CGFloat(planeAnchor.center.x)
let y = CGFloat(planeAnchor.center.y)
let z = CGFloat(planeAnchor.center.z)
planeNode.position = SCNVector3(x,y,z)
planeNode.eulerAngles.x = -.pi / 2
node.addChildNode(planeNode)
node.name = "plane"
loadSphere(x:x, y:y, z:z)
Im trying to put the sphere right in the middle of a plane as such:
func loadSphere (x:CGFloat, y:CGFloat, z:CGFloat) {
let idleScene = SCNScene(named: "art.scnassets/bounceFixed.dae")!
// This node will be parent of all the animation models
let node = SCNNode()
for child in idleScene.rootNode.childNodes {
node.addChildNode(child)
}
// Set up some properties
node.name = "Sphere"
node.position = SCNVector3(x, y, z)
node.scale = SCNVector3(0.001, 0.001, 0.001)
...
But the issue is that whenever I run this, x, y, z, all end up being zero. I've tried things like sceneView.scene.rootNode.childNodes[3].worldPosition
or node.worldPosition
but that always ends up generating the sphere right in the view of the camera and not in the middle of the plane.
I've attached a picture here to show you what I mean by the "middle".
Please let me know how I can remedy this.
EDIT: My goal with this post is to try to get the x, y, z (center) of the plane node without appending the sphere as a child.
Best.
Without actually seeing your model, or exactly how you are adding your Sphere, I would hazard a guess, that either you aren't adding your model to the correct SCNNode
, or that the pivot
of your model is not centered.
If you want to place something centrally on your SCNNode with a plane geometry you can set it's position at SCNVector3Zero
or ommit it altogether e.g.
/// Loads An SCNSphere On A Generated SCNNode
///
/// - Parameter plane: SCNNode
func loadSphereOnPlane(_ plane: SCNNode) {
let sphereNode = SCNNode()
let sphereNodeGeometry = SCNSphere(radius: 0.01)
sphereNodeGeometry.firstMaterial?.diffuse.contents = UIColor.cyan
sphereNode.geometry = sphereNodeGeometry
plane.addChildNode(sphereNode)
}
Whereby you would call this at the end of the rendererDidAddNode
delegate callback e.g:
loadSphereOnPlane(planeNode)
If the pivot of your model is not centered you can use something like this to alter it:
/// Changes The Pivot To The Center Of The Model
///
/// - Parameter model: SCNNode
func createCentralPivotFor(_ model: SCNNode){
let (min, max) = model.boundingBox
let dx = min.x + 0.5 * (max.x - min.x)
let dy = min.y + 0.5 * (max.y - min.y)
let dz = min.z + 0.5 * (max.z - min.z)
model.pivot = SCNMatrix4MakeTranslation(dx, dy, dz)
}
An example usage might thus be like so:
/// Loads Our Little Scatterbug
func loadScatterBugOnPlane(_ node: SCNNode) {
let modelPath = "ARModels.scnassets/Scatterbug.scn"
//1. Get The Reference To Our SCNScene & Get The Model Root Node
guard let model = SCNScene(named: modelPath),
let pokemonModel = model.rootNode.childNode(withName: "RootNode", recursively: false) else { return }
let scatterBug = pokemonModel
//2. Scale The Scatterbug
scatterBug.scale = SCNVector3(0.002, 0.002, 0.002)
//3. Set The Pivot
createCentralPivotFor(scatterBug)
//4. Add It To The Plane
node.addChildNode(scatterBug)
}
Which you could also call at the end of the rendererDidAddNode delegate callback e.g:
Both methods result in something like this:
Update:
Since you have now changed your question, you can try something like this:
/// Loads An SCNSphere At The Position Of An ARAnchor
///
/// - Parameter plane: SCNNode
func loadSphereAtAnchorPosition(_ anchor: ARPlaneAnchor) {
let sphereNode = SCNNode()
let sphereNodeGeometry = SCNSphere(radius: 0.01)
sphereNodeGeometry.firstMaterial?.diffuse.contents = UIColor.cyan
sphereNode.geometry = sphereNodeGeometry
sphereNode.position = SCNVector3(anchor.transform.columns.3.x,
anchor.transform.columns.3.y,
anchor.transform.columns.3.z)
augmentedRealityView?.scene.rootNode.addChildNode(sphereNode)
}
Hope it helps...