SceneKit做一个旋转的地球效果

时间:2023-12-13 11:29:38

SceneKit可以用寥寥几行帮你完成很多OpenGL复杂的3D设置代码,下面本猫就带大家完成一个旋转的3D地球的场景.

首先需要地球表面图片,将其导入到Xcode中:

SceneKit做一个旋转的地球效果

我们用SceneKit内置的几何球体类创建一个球的实例,并且将地球表面图片应用在球的表面上:

let globe = SCNSphere(radius: 15.0)
let globeNode = SCNNode(geometry: globe)
globeNode.position = SCNVector3(x: 20, y: 40, z: -50)

globeNode.geometry?.firstMaterial?.diffuse.contents = UIImage(named: "earthDiffuse.jpg")
globeNode.geometry?.firstMaterial?.diffuse.mipFilter = .Linear

接着我们利用CoreAnimation给我们提供的动画,让球体绕其y轴旋转:

let rotation = CABasicAnimation(keyPath: "rotation")
rotation.fromValue = NSValue(SCNVector4: SCNVector4(x: 0, y: 0, z: 0, w: 0))
rotation.toValue = NSValue(SCNVector4: SCNVector4(x: 0, y: 1, z: 0, w: Float(M_PI*2.0)))
rotation.duration = 10
rotation.repeatCount = .infinity
globeNode.addAnimation(rotation, forKey: "rotation")

为了增加些funny,我们同时将球在旋转的同时上下移动,并且不停地变大和缩小,这些都可以利用CoreAnimation的SCNAction类来完成:

let moveGlobeUp = SCNAction.moveByX(0.0, y: 10.0, z: 0.0, duration: 1.0)
        let moveGlobeDown = SCNAction.moveByX(0.0, y: -10.0, z: 0.0, duration: 1.0)
        let seq = SCNAction.sequence([moveGlobeUp,moveGlobeDown])
        let repeatSeq = SCNAction.repeatActionForever(seq)
        globeNode.runAction(repeatSeq)

        let scaleUp = SCNAction.scaleTo(5.0, duration: 5.0)
        let scaleDown = SCNAction.scaleTo(0.5, duration: 5.0)
        let repeatSeq2 = SCNAction.repeatActionForever(SCNAction.sequence([scaleDown,scaleUp]))
        globeNode.runAction(repeatSeq2)

就此可见,Cocoa里关于动画的东西都是相通的,在View,Layer中学习的动画效果,很容易的可以拿到3D中来用,十分方便,使得再学习成本很低.

运行一下App,效果如下(动态图有点大,加载请稍等片刻):

SceneKit做一个旋转的地球效果

大家可以看到游戏场景中不但完成了节点的动画,也增加了环境光和透射光的效果,原来需要用复杂OpenGL完成的事,现在基本上毫不费力了 ;]