Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
I've two objects in one SceneKit. One is the Earth and the other is the Moon. Both of them are positioned at x:0, y:0, z:0 and are overlapping. How should I change the coordinates of the Moon so it's around the Earth?
Here the code:
import UIKit
import SceneKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let scene = SCNScene()
let cameraNode = SCNNode()
cameraNode.camera = SCNCamera()
cameraNode.position = SCNVector3(x:0, y:0, z:10)
scene.rootNode.addChildNode(cameraNode)
let lightNode = SCNNode()
lightNode.light = SCNLight()
lightNode.light?.type = .directional
lightNode.position = SCNVector3(x:0, y:0, z:2)
scene.rootNode.addChildNode(lightNode)
let stars = SCNParticleSystem(named: "StarsParticles.scnp", inDirectory: nil)!
scene.rootNode.addParticleSystem(stars)
let moonNode = MoonNode()
scene.rootNode.addChildNode(moonNode)
let sceneview = self.view as! SCNView
sceneview.scene = scene
let earthNode = EarthNode()
scene.rootNode.addChildNode(earthNode)
let sceneView = self.view as! SCNView
sceneView.scene = scene
sceneView.showsStatistics = false
sceneView.backgroundColor = UIColor.black
sceneView.allowsCameraControl = true
override var prefersStatusBarHidden: Bool {
return true
You could make your view controller a SCNSceneRendererDelegate
, and implement the delegate method renderer:willRenderScene
which gives you a time
. Based on that time
, you can set something like this:
moonNode.position = SCNVector3(r * cos(Float(time), r * sin(Float(time)), 0)
where r
is the radius of your Earth node - if you don't know this at compile time, just include something like this above that line:
let r = length(float3(earthNode.boundingBox.max) - float3(earthNode.boundingBox.min))
this won't quite be exact for the code I included which causes a rotation in the xy plane but it will at least give you the right order of magnitude for r
. If you get an error that it can't find float3 or length, try and import simd
.
Let me know if you have any issues with this, as I typed this up from memory.
More info in documentation: https://developer.apple.com/documentation/scenekit/scnscenerendererdelegate/1523483-renderer
You can easily do it using simdPivot
instance property.
var simdPivot: simd_float4x4 { get set }
Here's a code for testing:
import SceneKit
class GameViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let scene = SCNScene()
let action = SCNAction.repeatForever(SCNAction.rotate(by: .pi,
around: SCNVector3(0,1,0),
duration: 1))
let earthNode = SCNNode(geometry: SCNSphere(radius: 3.57))
earthNode.geometry?.materials.first?.diffuse.contents = UIColor.blue
scene.rootNode.addChildNode(earthNode)
let moonNode = SCNNode(geometry: SCNSphere(radius: 0.15))
moonNode.geometry?.materials.first?.diffuse.contents = UIColor.yellow
moonNode.simdPivot.columns.3.x = 5
moonNode.runAction(action)
scene.rootNode.addChildNode(moonNode)
let sceneView = self.view as! SCNView
sceneView.scene = scene
sceneView.backgroundColor = UIColor.black
sceneView.allowsCameraControl = true
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.