Есть ли способ сделать движущиеся / меняющиеся тени на Scenekit (как восходящее солнце)?

Мой основной код в значительной степени описан в этом руководстве: https://code.tutsplus.com/tutorials/an-introduction-to-scenekit-fundamentals--cms-23847

Я хочу сделать поведение на рассвете. Нечто подобное lightNode начинается на той же высоте, что и ограниченный cubeNode, и перемещает его вверх, чтобы тень со временем уменьшалась. Поэтому я попытался переместить узлы через SCNAction.move(в...).

Действие на lightNode -> ничего не происходит

Действие на ограниченном cubeNode -> тень начинает мерцать, но без изменений

Я пробовал с shadowModes. Я думаю, что я неправильно понял это. Никаких полезных результатов не получилось.

У кого-нибудь есть идея, если scenekit поддерживает что-то вроде динамического изменения теней?

2 ответа

Решение

Я нашел способ сделать это. Мои главные ошибки были:

  1. Почему-то это не работает для доступа к lightNode (это просто не имеет никакого эффекта, когда действия для lightNode называются)

  2. Я пытался пройти через SCNAction.move(to...), Ответ заключается в использовании вращения вместо продольного движения.

Ответом был доступ к узлу ограничения (вместо lightNode). В этом коде кубический узел заменяется невидимым centerPoint (как узел ограничения, где lightNode должен смотреть). boxNodeбыл добавлен для создания холста для тени. lightNodeдолжен быть добавлен к centerPointНЕ на сцену.

Есть модифицированный viewDidLoad-метод. Если вы хотите проверить это, откройте Xcode, запустите новый проект под названием SceneKit Game и замените viewDidLoad со следующим кодом.

    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)
}

Существует также изменение цвета света считается. С CABasicAnimation можно изменить light.color-свойство со временем. Это не идеальный рассвет со всеми цветовыми шагами, но есть также способ связать эти анимации, чтобы сделать их более сложными. (Для этого поиска "wenderlich, как создать сложную загрузочную анимацию".

Но я не нашел способа изменить цвет тени. Это может быть хорошим эффектом иметь белые тени в ночное время и черные тени в дневное время. light.shadowColor не помогло еще. Если у кого-то есть идея, это очень ценится.

Да. Вы можете сделать красивую движущуюся тень. Если ваш прожектор не движется, это может быть из-за того, что в руководстве вы наложили на него ограничение. Попробуйте удалить его.

// lightNode.constraints = [constraint]
Другие вопросы по тегам