2019年3月7日木曜日

ARKitのサンプルにアニメーションを追加しよう



ARKitのサンプルにアニメーションを追加しよう


今回扱うのはアニメーションです。

ただAR空間の物体に動きが入るとよりリアルさが出て楽しくなります。


アニメーションの設定方法


アニメーションの設定方法は大きく3つあります。

  • SCNAction
  • SCNTransaction
  • CoreAnimation


SCNAction


直進や回転、拡大縮小、フェードイン/フェードアウトをそれぞれ対応したActionを使ってAR上の物体にアニメーションを適用することができます。


SCNTransaction


AR空間の物体は60FPSのループで常に描画されていますが、その間隔を伸ばすことによりアニメーションを設定することができます。

イメージとしては物体を1m右に動かすことを1秒かけて行うことで、その間の動きが描画される感じです。



CoreAnimation


通常AR空間に表示する3DオブジェクトはBlenderなどの3Dモデリングツールを使って作られますが、3Dモデリングツールでは形を作るだけでなくオブジェクトにアニメーションを設定することができます。

そのような、外部ツールで設定されたアニメーションを呼び出すことでアニメーションを描画することができます。

キャラクターが歩くなどの複雑なアニメーションの場合は大抵CoreAnimationを使います。




修正方針


今回は次の2つのアニメーションをそれぞれ別の方法で実装してみます。

  1. 平面検知された時に表示される飛行機をフェードインさせる
  2. 飛行機をきりもみ回転させる


飛行機のフェードイン


SCNTransactionと、物体の透過を設定するopacityというプロパティを使って実装します。

まずARKitサンプルの飛行機を平面に置いてみようでshipの初期状態をHiddenにしましたが、これをopacityに変更しておきます。

ship.opacity = 0
このopacityは0〜1が設定でき、0が完全に透明な状態を示します。

次に、func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor)で飛行機を置いていますが、この処理の最後に次のSCNTransaction処理を追加します。
SCNTransaction.begin()
SCNTransaction.animationDuration = 1.5

ship.opacity = 1
SCNTransaction.commit()


飛行機のきりもみ回転


単純に飛行機を回転させる場合は次の2行で実装できます。

let rotationAction = SCNAction.repeatForever(SCNAction.rotateBy(x: 0, y: 0, z: 1, duration: 1))
ship.runAction(rotationAction)

しかし、これを単純にshipに追加してしまうと、フェードインしている状態で回転をしてしまいます。

フェードインが完了してから回転をしたい場合は次のように実装をします。

let completion = {
    let rotationAction = SCNAction.repeatForever(SCNAction.rotateBy(x: 0, y: 0, z: 1, duration: 1))
    ship.runAction(rotationAction)
}

SCNTransaction.begin()
SCNTransaction.animationDuration = 1.5
SCNTransaction.completionBlock = completion
ship.opacity = 1

SCNTransaction.commit()

実際に動作している様子




実際のコード

import UIKit
import SceneKit
import ARKit

class ViewController: UIViewController, ARSCNViewDelegate {

    @IBOutlet var sceneView: ARSCNView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Set the view's delegate
        sceneView.delegate = self
        
        // Show statistics such as fps and timing information
        sceneView.showsStatistics = true
        
        // Create a new scene
        let scene = SCNScene(named: "art.scnassets/ship.scn")!
        
        if let ship = scene.rootNode.childNode(withName: "ship", recursively: true) {
            ship.opacity = 0
        }
        
        // Setup Omni Light
        let light = SCNLight()
        light.type = .omni

        let LightNode = SCNNode()
        LightNode.light = light
        LightNode.name = "light"
        LightNode.position = SCNVector3(-1,2,-1)
        scene.rootNode.addChildNode(LightNode)
        
        // Set the scene to the view
        sceneView.scene = scene
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        
        // Create a session configuration
        let configuration = ARWorldTrackingConfiguration()
        configuration.planeDetection = [.horizontal]
        
        // Run the view's session
        sceneView.session.run(configuration)
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        
        // Pause the view's session
        sceneView.session.pause()
    }

    // MARK: - ARSCNViewDelegate
    
/*
    // Override to create and configure nodes for anchors added to the view's session.
    func renderer(_ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode? {
        let node = SCNNode()
     
        return node
    }
*/
    func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
        
        if let ship = sceneView.scene.rootNode.childNode(withName: "ship", recursively: true) {
            ship.removeFromParentNode()
            node.addChildNode(ship)
            
            let configuration = ARWorldTrackingConfiguration()
            sceneView.session.pause()
            sceneView.session.run(configuration)
            
            let completion = {
                let rotationAction = SCNAction.repeatForever(SCNAction.rotateBy(x: 0, y: 0, z: 1, duration: 1))
                ship.runAction(rotationAction)
            }
            
            SCNTransaction.begin()
            SCNTransaction.animationDuration = 1.5
            SCNTransaction.completionBlock = completion
            ship.opacity = 1
            SCNTransaction.commit()
        }
    }
    
    func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
        guard let lightEstimate = self.sceneView.session.currentFrame?.lightEstimate else { return }
        let ambientIntensity = lightEstimate.ambientIntensity
        let ambientColorTemperature = lightEstimate.ambientColorTemperature
        
        if let lightNode = self.sceneView.scene.rootNode.childNode(withName: "light", recursively: true) {
            guard let light = lightNode.light else { return }
            light.intensity = ambientIntensity
            light.temperature = ambientColorTemperature
        }
    }
    
    func session(_ session: ARSession, didFailWithError error: Error) {
        // Present an error message to the user
        
    }
    
    func sessionWasInterrupted(_ session: ARSession) {
        // Inform the user that the session has been interrupted, for example, by presenting an overlay
        
    }
    
    func sessionInterruptionEnded(_ session: ARSession) {
        // Reset tracking and/or remove existing anchors if consistent tracking is required
        
    }
}


2 件のコメント:

  1. Some methods melt or soften the fabric to provide the layers. In fused filament fabrication, recognized as|also called|also referred to as} fused deposition modeling , the model or part is produced by extruding small beads White Bath Sheets or streams of material which harden immediately to kind layers. A filament of thermoplastic, metallic wire, or other materials is fed into an extrusion nozzle head , which heats the fabric and turns the circulate on and off. FDM is somewhat restricted within the variation of shapes might be|that might be|which may be} fabricated. Another technique fuses parts of the layer and then moves upward within the working space, including another layer of granules and repeating the method until the piece has constructed up. This process makes use of the unfused media to support overhangs and skinny walls within the part being produced, which reduces the necessity for temporary auxiliary supports for the piece.

    返信削除
  2. Free spins are exactly because the name implies, spins would possibly be} free of cost. These bonuses can encompass a mixture of free spins and free money. They are regularly provided as much-appreciated bonus rewards or as a welcome bonus. It kind of|is kind of} common that gamers win free spins whereas half in} on slot machines which will to} trigger the machine to proceed to spin without extra costs. While casinos scrutinize gamers in every different area 온라인카지노 of the on line casino, poker gamers get more leeway because of|as a result of} casinos don’t have as a lot money at stake. That’s because of|as a result of} gamers are betting their own bucks, and the house will get a reduce regardless of who wins.

    返信削除