ARKit - 2. 텍스쳐와 표면

Dave·2022년 8월 3일
0

텍스쳐와 표면을 다루는 방법을 배우고 이를 통해 지구를 만들어보자

지구만들기

이와 같이 지구를 감쌀 수 있는 이미지를 다운받아 Asset에 추가한다.

import UIKit
import ARKit

class ViewController: UIViewController {
    
    @IBOutlet weak var sceneView: ARSCNView!
    let configuration = ARWorldTrackingConfiguration()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.sceneView.debugOptions = [ARSCNDebugOptions.showWorldOrigin, ARSCNDebugOptions.showFeaturePoints]
        self.sceneView.session.run(configuration)

    }
    
    override func viewDidAppear(_ animated: Bool) {
        let earth = SCNNode()
        // 구체를 하나 생성한다.
        
        earth.geometry = SCNSphere(radius: 0.2)
        earth.geometry?.firstMaterial?.diffuse.contents = #imageLiteral(resourceName: "Earth")
        // 구체의 텍스쳐에 저장해놓은 이미지를 선택하여 설정해준다.
        
        earth.position = SCNVector3(0,0, -1)
        self.sceneView.scene.rootNode.addChildNode(earth)
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}

회전시키기

    override func viewDidAppear(_ animated: Bool) {
        let earth = SCNNode()
        earth.geometry = SCNSphere(radius: 0.2)
        earth.geometry?.firstMaterial?.diffuse.contents = #imageLiteral(resourceName: "Earth")
        earth.position = SCNVector3(0,0, -1)
        self.sceneView.scene.rootNode.addChildNode(earth)
        
        let action = SCNAction.rotateBy(x: 0, y: CGFloat(360.degreeToRadians), z: 0, duration: 8)
        // y축을 기준으로 8초동안 회전시키기
        
        earth.runAction(action)
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}

extension Int {
    var degreeToRadians: Double { return Double(self) * .pi / 180 }
}

무한대로 회전시키기

import UIKit
import ARKit

class ViewController: UIViewController {
    
    @IBOutlet weak var sceneView: ARSCNView!
    let configuration = ARWorldTrackingConfiguration()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.sceneView.debugOptions = [ARSCNDebugOptions.showWorldOrigin, ARSCNDebugOptions.showFeaturePoints]
        self.sceneView.session.run(configuration)
        self.sceneView.autoenablesDefaultLighting = true

    }
    
    override func viewDidAppear(_ animated: Bool) {
        let earth = SCNNode()
        earth.geometry = SCNSphere(radius: 0.2)

        earth.position = SCNVector3(0,0, -1)
        self.sceneView.scene.rootNode.addChildNode(earth)
        
        let action = SCNAction.rotateBy(x: 0, y: CGFloat(360.degreeToRadians), z: 0, duration: 8)
        let forever = SCNAction.repeatForever(action)
        // 무한대로 회전시키는 메서드
        
        earth.runAction(forever)
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}

extension Int {
    var degreeToRadians: Double { return Double(self) * .pi / 180 }
}

반사(Specular)

지구의 바다부분에 빛이 반사되는 효과를 넣어보자


빛 반사를 표현 할 수 있는 specular 이미지이다.


import UIKit
import ARKit

class ViewController: UIViewController {
    
    @IBOutlet weak var sceneView: ARSCNView!
    let configuration = ARWorldTrackingConfiguration()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.sceneView.debugOptions = [ARSCNDebugOptions.showWorldOrigin, ARSCNDebugOptions.showFeaturePoints]
        self.sceneView.session.run(configuration)
      ⭐️ self.sceneView.autoenablesDefaultLighting = true ⭐️ 

    }
    
    override func viewDidAppear(_ animated: Bool) {
        let earth = SCNNode()
        earth.geometry = SCNSphere(radius: 0.2)
        
        earth.geometry?.firstMaterial?.diffuse.contents = #imageLiteral(resourceName: "Earth") // 표면 
        ⭐️ earth.geometry?.firstMaterial?.specular.contents = #imageLiteral(resourceName: "Earth Specular") // 반사 ⭐️ 
        // 객체의 표면에 반사효과를 넣는 메서드
       
        earth.position = SCNVector3(0,0, -1)
        self.sceneView.scene.rootNode.addChildNode(earth)
        
        let action = SCNAction.rotateBy(x: 0, y: CGFloat(360.degreeToRadians), z: 0, duration: 8)
        let forever = SCNAction.repeatForever(action)
        
        earth.runAction(forever)
    }

바다쪽에 빛이 반사되는 것을 확인 할 수 있다.

방출(Emission)

지구에 구름효과를 넣어보자

빛 반사를 표현 할 수 있는 cloud 이미지이다.

    override func viewDidAppear(_ animated: Bool) {
        let earth = SCNNode()
        earth.geometry = SCNSphere(radius: 0.2)
        earth.geometry?.firstMaterial?.diffuse.contents = #imageLiteral(resourceName: "Earth") 
        earth.geometry?.firstMaterial?.specular.contents = #imageLiteral(resourceName: "Earth Specular") 
        ⭐️earth.geometry?.firstMaterial?.emission.contents = #imageLiteral(resourceName: "Earth Emission")⭐️ 
        // 객체의 표면에 방출효과를 넣는 메서드

        earth.position = SCNVector3(0,0, -1)
        self.sceneView.scene.rootNode.addChildNode(earth)
        
        let action = SCNAction.rotateBy(x: 0, y: CGFloat(360.degreeToRadians), z: 0, duration: 8)
        let forever = SCNAction.repeatForever(action)
        
        earth.runAction(forever)
    }

아까 넣었던 반사효과와 함께 지구의 구름까지 확인 할 수 있다.

일반(Normal)

토지의 물리적 특성들을 확인 할 수 있는 normal 이미지

 override func viewDidAppear(_ animated: Bool) {
        let earth = SCNNode()
        earth.geometry = SCNSphere(radius: 0.2)
        earth.geometry?.firstMaterial?.diffuse.contents = #imageLiteral(resourceName: "Earth") // 표면
        earth.geometry?.firstMaterial?.specular.contents = #imageLiteral(resourceName: "Earth Specular") // 반사
        earth.geometry?.firstMaterial?.emission.contents = #imageLiteral(resourceName: "Earth Emission") // 방출
        earth.geometry?.firstMaterial?.normal.contents = #imageLiteral(resourceName: "Earth Normal") // 일반
        
        earth.position = SCNVector3(0,0, -1)
        self.sceneView.scene.rootNode.addChildNode(earth)
        
        let action = SCNAction.rotateBy(x: 0, y: CGFloat(360.degreeToRadians), z: 0, duration: 8)
        let forever = SCNAction.repeatForever(action)
        
        earth.runAction(forever)
    }

육지의 물리적 특성들을 자세히 볼 수 있다.

다른 행성 만들기

태양

태양은 태양계의 중심이니까 지구를 태양의 자식노드로 추가해준다.


import UIKit
import ARKit

class ViewController: UIViewController {
    
    @IBOutlet weak var sceneView: ARSCNView!
    let configuration = ARWorldTrackingConfiguration()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.sceneView.debugOptions = [ARSCNDebugOptions.showWorldOrigin, ARSCNDebugOptions.showFeaturePoints]
        self.sceneView.session.run(configuration)
        self.sceneView.autoenablesDefaultLighting = true

    }
    
    override func viewDidAppear(_ animated: Bool) {
        let sun = SCNNode(geometry: SCNSphere(radius: 0.35))
        sun.geometry?.firstMaterial?.diffuse.contents = #imageLiteral(resourceName: "Sun diffuse")
        sun.position = SCNVector3(0, 0, -1)
        self.sceneView.scene.rootNode.addChildNode(sun)
        
        
       
     ⭐️ let earth = planet(geometry: SCNSphere(radius: 0.2), diffuse: #imageLiteral(resourceName: "Earth"), specular: #imageLiteral(resourceName: "Earth Specular"), emission: #imageLiteral(resourceName: "Earth Emission"), normal: #imageLiteral(resourceName: "Earth Normal"),
                           position: SCNVector3(1.2 ,0 ,-1)) ⭐️
    
        
       
        sun.addChildNode(earth)
        
      
    }
    
    
    
    ⭐️  func planet(geometry: SCNGeometry, diffuse: UIImage, specular: UIImage, emission: UIImage,
                normal: UIImage, position: SCNVector3) -> SCNNode {
        let planet = SCNNode(geometry: geometry)
        planet.geometry?.firstMaterial?.diffuse.contents = diffuse
        planet.geometry?.firstMaterial?.specular.contents = specular
        planet.geometry?.firstMaterial?.emission.contents = emission
        planet.geometry?.firstMaterial?.normal.contents = normal
        planet.position = position
        
        return planet
    }
    // 행성을 만드는 함수를 정의하여 코드를 간결하게 만들어준다 ⭐️
    

금성

금성도 태양의 자식노드로 추가해준다.

import UIKit
import ARKit

class ViewController: UIViewController {
    
    @IBOutlet weak var sceneView: ARSCNView!
    let configuration = ARWorldTrackingConfiguration()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.sceneView.debugOptions = [ARSCNDebugOptions.showWorldOrigin, ARSCNDebugOptions.showFeaturePoints]
        self.sceneView.session.run(configuration)
        self.sceneView.autoenablesDefaultLighting = true

    }
    
    override func viewDidAppear(_ animated: Bool) {
        let sun = SCNNode(geometry: SCNSphere(radius: 0.35))
        sun.geometry?.firstMaterial?.diffuse.contents = #imageLiteral(resourceName: "Sun diffuse")
        sun.position = SCNVector3(0, 0, -1)
        self.sceneView.scene.rootNode.addChildNode(sun)
        
        
        let earth = planet(geometry: SCNSphere(radius: 0.2), diffuse: #imageLiteral(resourceName: "Earth"), specular: #imageLiteral(resourceName: "Earth Specular"), emission: #imageLiteral(resourceName: "Earth Emission"), normal: #imageLiteral(resourceName: "Earth Normal"),
                           position: SCNVector3(1.2 ,0 ,0))
        
        ⭐️ let venus = planet(geometry: SCNSphere(radius: 0.1), diffuse: #imageLiteral(resourceName: "Sun diffuse"), specular: nil, emission: #imageLiteral(resourceName: "Venus Atmosphere"), normal: nil,
                           position: SCNVector3(1.8 ,0, 0))
                           
   		// planet함수를 이용하여 venus도 만들어준다. ⭐️

        sun.addChildNode(earth)
        ⭐️ sun.addChildNode(venus) ⭐️
        

 
    }
    
    func planet(geometry: SCNGeometry, diffuse: UIImage, specular: UIImage?, emission: UIImage?,
                normal: UIImage?, position: SCNVector3) -> SCNNode {
        let planet = SCNNode(geometry: geometry)
        planet.geometry?.firstMaterial?.diffuse.contents = diffuse
        planet.geometry?.firstMaterial?.specular.contents = specular
        planet.geometry?.firstMaterial?.emission.contents = emission
        planet.geometry?.firstMaterial?.normal.contents = normal
        planet.position = position
        
        return planet
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}

profile
iOS Developer

0개의 댓글