my basic code is pretty much this on that tutorial: https://code.tutsplus.com/tutorials/an-introduction-to-scenekit-fundamentals--cms-23847
I want to make a sunrise behaviour. Something like the lightNode begins on the same height as the constrained cubeNode and move it up so that the shadow shall become smaller over time. Therefore I tried to move the nodes via SCNAction.move(to...).
Action on lightNode -> nothing happens
Action on the constrained cubeNode -> shadow starts to flicker, but no changing
I tried around with the shadowModes. I think I misunderstood this. No useful results came up.
Has anyone an idea if scenekit supports something like dynamicly changing shadows?
I found a way to make it. My major mistakes were:
Somehow it does not work to access the lightNode (it just has no effect, when actions for a lightNode
are called)
I tried to go via SCNAction.move(to...)
. The answer is to use a rotation instead of a longitudinal movement.
The answer was accessing the constraint Node (instead of the lightNode). In this code the cubeNode is replaced with an invisible centerPoint
(as the constraint node where the lightNode
has to look at). A boxNode
has been added for making a canvas for the shadow. The lightNode
has to be added to the centerPoint
, NOT to the scene.
There is the modified viewDidLoad
-method. If you want to check this out, open Xcode, start a new project as SceneKit Game and replace the viewDidLoad
with the following code.
override func viewDidLoad() {
super.viewDidLoad()
// create a new scene
let scene = SCNScene(named: "art.scnassets/ship.scn")!
// create and add a camera to the scene
let cameraNode = SCNNode()
cameraNode.camera = SCNCamera()
scene.rootNode.addChildNode(cameraNode)
// place the camera
cameraNode.position = SCNVector3(x: 0, y: 0, z: 15)
// create and add a light to the scene
let centerPoint = SCNNode.init()
centerPoint.position = SCNVector3Make(0, 0, 0)
scene.rootNode.addChildNode(centerPoint)
let light = SCNLight()
light.type = SCNLight.LightType.spot
light.spotInnerAngle = 30
light.spotOuterAngle = 80
light.castsShadow = true
light.color = UIColor.init(colorLiteralRed: 0.95, green: 0.8, blue: 0.8, alpha: 1)
light.zFar = 200
let lightNode = SCNNode()
lightNode.light = light
lightNode.position = SCNVector3Make(20, 100, 50)
let constraint = SCNLookAtConstraint(target: centerPoint)
constraint.isGimbalLockEnabled = true
lightNode.constraints = [constraint]
centerPoint.addChildNode(lightNode)
let ambientLight = SCNLight.init()
ambientLight.type = SCNLight.LightType.ambient
ambientLight.color = UIColor.darkGray
scene.rootNode.light = ambientLight
// retrieve the ship node
let material = SCNMaterial.init()
material.diffuse.contents = UIColor.yellow
material.lightingModel = SCNMaterial.LightingModel.phong
material.locksAmbientWithDiffuse = true
let boxNode = SCNNode.init(geometry: SCNBox.init(width: 10, height: 0.1, length: 10, chamferRadius: 0))
boxNode.geometry?.firstMaterial = material
boxNode.position = SCNVector3Make(0, -2, 0)
scene.rootNode.addChildNode(boxNode)
// animate spot light rotation
centerPoint.runAction(SCNAction.repeatForever(SCNAction.rotateBy(x: CGFloat(M_PI), y: 0, z: CGFloat(M_PI), duration: 5)))
// animate color light change
let lightColorChange: CABasicAnimation = CABasicAnimation.init(keyPath: "color")
lightColorChange.fromValue = UIColor.init(colorLiteralRed: 0.95, green: 0.8, blue: 0.8, alpha: 1)
lightColorChange.toValue = UIColor.init(colorLiteralRed: 0, green: 0, blue: 0.4, alpha: 1)
lightColorChange.duration = 5.0
lightColorChange.autoreverses = true
lightColorChange.repeatCount = Float.infinity
light.addAnimation(lightColorChange, forKey: "changeLight")
// retrieve the SCNView
let scnView = self.view as! SCNView
// set the scene to the view
scnView.scene = scene
// allows the user to manipulate the camera
scnView.allowsCameraControl = true
// show statistics such as fps and timing information
scnView.showsStatistics = true
// configure the view
scnView.backgroundColor = UIColor.black
// add a tap gesture recognizer
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(_:)))
scnView.addGestureRecognizer(tapGesture)
}
There is also a color change of the light is considered. With a CABasicAnimation it is possible to change the light.color
-property over time. It is not like a perfect sunrise with all color steps, but there is also a way to chain those animations to make it more complex. (For this search for "wenderlich how to create a complex loading animation".
But I did not find a way to change the shadow color. It could be a nice effect to have white shadows on nighttime and black shadows on daytime. light.shadowColor
did not help yet. If someone has an idea it is very appreciated.