apple/VisionOS, ARKit

[SceneKit] #4 SCNAction

lgvv 2023. 8. 13. 22:15

SCNAction

시작하기 전 간단정리

SceneKit에서 명시적 애니메이션: Core Animation

SceneKit에서 암시적 애니메이션: SCNTransaction

SCNAction은?: 그룹핑, 시퀀스, 싱글 등 조합 가능.

 

연결한 모든 노드의 속성을 변경하는 간단하고 재사용 가능한 애니메이션.

class SCNAction : NSObject

 

SCNNode액션 이 연결된 객체의 구조와 내용을 변경하기 위해 액션을 사용하지만 액션을 사용하여 scene에 다른 변경을 줄 수 있음. SceneKit에서 액션은 사용자 입력에 따라 자주 변경되는 애니메이션 동작을 구현하는 쉬운 방법을 제공함.

 

# Working with Actions

action을 생성하기 위해서는 action과 관련이 있는 메서드의 클래스는 호출한다. 그러나나서 액션의 프로퍼티를 구성한다. 마지막으로 액션을 실행하며, 노드 객체의 run 메소드(또는 SCNActionable 프로토콜의 유사한 메소드)를 호출하고 이를 객체에 전달한다.

 

대부분의 액션들에서 노드의 위치와 회전 또는 크기 등의 프로퍼티를 바꿀 것을 허용함. scene이 렌더링되는 둘 이상의 프레임에서 연결된 노드의 속성을 변경함. duration 속성은 애니메이션 되는 동안 걸리는 시간을 나타내고, timing Modespeed는 해당 애니메이션이 걸리는 속도를 나타낸다. 액션의 프로퍼티값을 조정해 재생 속도를 높이거나 낮추어 애니메이션의 타임이 조정 가능.

 

몇몇 액션들은 다른 액션의 하위(childern) 작업에 속한다.

 - 하나의 시퀀스 액션은 여러개의 하위 액션들을 가진다. 시퀀스 안에서 각각의 액션은 이전 액션들이 끝나고 난 후에 시작한다.

 - 그룹 액션은 여러개의 하위 액션들을 가진다. 모든 액션들은 같은 시간에 시작되도록 그룹 안에 저장되어 있다.

 - 반복액션들은 하나의 자식 액션으로 정의되어 있다. 액션이 완료되면 그것을 재시작한다.

 

시퀀스, 그룹, 반복 액션간의 중첩이 가능하고 이를 결합함으로써 각 노드에 더 정교한 조작을 수행할 수 있다.

 

# Using Actions for Scene Animation

액션들이 쉽게 재상요 되더라도 running하는 동안에 추가하거나 제거할 수 있다. 그리고 직접적으로 보여지는 노드에 영향을 줄 수 있다. 이러한 이유로, 액션들은 게임을 빌드할 때와 같이 사용자 입력에 대한 응답으로 scene이 자주 변경될 때도 잘 작동한다. 액션을 사용하면 scene의 모든 요소에 애니메이션을 적용할 수 있는건 아니다. 암시적으로 애니메이션을 적용하기 위한 (SCNTransaction)을 사용하거나 명시적으로 애니메이션을 사용하기위한(Core Animation - SCNAnimatable)을 사용하는 등 렌더링된 각 프레임에 대한 scene 그래프를 직접 변경한다. (SCNSceneRender Delegate를 참조하여)

 

func action_example() {
        let scene = SCNScene()
        arSceneView.scene = scene

        let boxGeometry = SCNBox(width: 1, height: 1, length: 1, chamferRadius: 0.1)
        
        var boxNode = SCNNode()
        boxNode = SCNNode(geometry: boxGeometry)
        boxNode.position = SCNVector3(0, 0, -5)
        
        let material = SCNMaterial()
        material.diffuse.contents = UIImage(resource: .pyramidFull)
        
        boxNode.geometry?.firstMaterial = material
        scene.rootNode.addChildNode(boxNode)

        let rotateAction = SCNAction.rotateBy(x: 0, y: .pi, z: 0, duration: 2)
        let moveAction = SCNAction.move(to: SCNVector3(0, 0, -10), duration: 2)
        let sequenceAction = SCNAction.sequence([rotateAction, moveAction])
        let repeatAction = SCNAction.repeatForever(sequenceAction)
        boxNode.runAction(repeatAction)
}

SCNAction

 

# 중첩 액션 사용예시

func action_example1() {
        let scene = SCNScene()
        arSceneView.scene = scene

        let boxGeometry = SCNBox(width: 1, height: 1, length: 1, chamferRadius: 0.1)
        
        var boxNode = SCNNode()
        boxNode = SCNNode(geometry: boxGeometry)
        boxNode.position = SCNVector3(0, 0, -15)
        
        let material = SCNMaterial()
        material.diffuse.contents = UIImage(resource: .pyramidFull)
        
        boxNode.geometry?.firstMaterial = material
        scene.rootNode.addChildNode(boxNode)

        // 회전 액션 생성
        let rotateAction = SCNAction.rotateBy(x: 0, y: CGFloat.pi * 2, z: 0, duration: 2.0)
        
        // 확대/축소 액션 생성
        let scaleUpAction = SCNAction.scale(to: 3.0, duration: 1.0)
        let scaleDownAction = SCNAction.scale(to: 1.0, duration: 1.0)
        
        // Group 액션 생성 (회전과 확대/축소 동시에)
        let groupAction = SCNAction.group([rotateAction, scaleUpAction])
        
        // 위의 Group 액션이 끝난 후에 확대/축소 액션 실행
        let sequenceAction = SCNAction.sequence([groupAction, scaleDownAction])
        
        // 노드에 액션 적용
        boxNode.runAction(sequenceAction)
    }

결과

 

해당 작업에 대한 타임라인 그래프

 

타임라인 설명

'apple > VisionOS, ARKit' 카테고리의 다른 글

[ARKit] #6 ARKit in iOS  (1) 2023.08.15
[SceneKit] #5 SCNSceneRendererDelegate  (0) 2023.08.15
[SceneKit] #3 Animating SceneKit Content  (0) 2023.08.13
[SceneKit] #2 Geometry 다뤄보기  (0) 2023.08.13
[ARKit] #1 ARKit 시작하기  (0) 2023.08.12