Kudan AR SDK で AR iOS アプリを作ってみよう〜マーカーレスで床に画像を表示

こんにちは。エクセルソフトの田淵です。

弊社取り扱いの Kudan AR SDK のエントリーです。

SDK のダウンロードは こちら からお申込みください。SDK を使った開発と、個人開発者のリリースは無料でご利用いただけます。企業の方は有料になりますので、@ytabuchi までご連絡ください。

前回の iOS のエントリーではマーカーの上に動画を表示させるところまでをやりました。

今回は遂にマーカレスです。

現時点でのサンプルコードは ytabuchi の Github にアップしてあります。この後もコミット追加していくのでスナップショットです。

作業の流れ

今までは Storyboard の最初の ViewController で作業していたので、ビューを分けたいと思います。

こんな感じですね。

  • Main.Storyboard を書き換え
  • ViewController.swiftMarkerViewController.swift に名前を変更して必要な参照を書き換え。
  • マーカーレスの処理を ArbiViewController.swift に新規に作成する

が作業内容です。Android 同様、ちょっと長いです。

また、今回使用する assets 画像一式は、こちら からダウンロードしてください。

Main.Storyboard を書き換え

初期画面のビューだけでしたので、ボタンでナビゲーション出来るように Storyboard を修正していきます。

右下の Object Library から、「Navigation Controller」をドラッグ&ドロップします。そのままだと右側の UITableView に遷移してしまうので以下を行います。

  • 右側の UITableView を削除します。
  • 新たに「ViewController」をドラッグ&ドロップして追加します。
  • 最初の View の左側に付いている「Storyboard Entry Point」の矢印を Navigation Controller にドラッグ&ドロップします。
  • Navigation Controller から「control」キーを押しながら上記で追加した新たなビューにドラッグ&ドロップして、「root view controller」として設定します。(以下で設定します)
  • ルートのビューのタイトル Navigation Item をクリックして、タイトルを修正します。

以下のような状態になるはずです。

次にルートのビューからマーカーのビューとマーカーレスのビューに遷移するようにボタンを2つ配置して、Segue を貼ります。以下を行います。

  • ルートのビューにボタンを2つ配置して、Constraints を設定しておきます。
  • 新しい「View Controller」を追加します。
  • ルートの2つのボタンから、control キーを押しながらそれぞれのビューにドラッグ&ドロップして Show Segue を繋げます。
  • 遷移先の各ページのタイトル部分には、「Navigation Item」をドラッグ&ドロップして追加しないと、タイトルを追加できないみたいです。

以下のような状態になっていれば OK です。

MarkerViewController.swift に参照を変更

元々あった「ViewController.swift」を MarkerViewController.swift に名前を変更して、ファイル内のクラス名も変更し、

class MarkerViewController: ARCameraViewController {

    @IBOutlet weak var clearButton: UIButton!
    @IBOutlet weak var imageButton: UIButton!
    @IBOutlet weak var modelButton: UIButton!
    @IBOutlet weak var videoButton: UIButton!
...

Storyboard の遷移先のページの identity inspector で MarkerViewController に割り当てを変更し直します。

マーカーレスの処理を ArbiViewController.swift に追加

マーカーレスの処理を追加する ViewController、ArbiViewController.swift を作成します。

Swift ファイルを作成してもクラスも import も何も書かれないので、次のコードを追加します。

import Foundation
import KudanAR

class ArbiViewController: ARCameraViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

マーカーレスのビューにボタン「changeTrackingModeButton」を追加して、ArbiViewController に Outlet と Action を追加します。

ARCameraViewController の override で必要になる setupContent() メソッドを追加しておきます。現時点で以下のようになります。ARImageNode のクラス変数もありますので、ご注意ください。

class ArbiViewController: ARCameraViewController {
    
    var trackingNode:ARImageNode?
    
    @IBOutlet weak var changeTrackingModeButton: UIButton!
    
    @IBAction func changeTrackingModeButton_TouchUpInside(_ sender: Any) {
        
    }
    
    override func setupContent() {
        
    }

    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

setupContent メソッドから呼び出す 2つのメソッドを追加

表示する TrackingNode を追加する addTrackingNode() メソッドを追加します。次のようなコードを setupContent の下に追加します。

func addTrackingNode() {
    
    // トラッキング(表示)するノードを用意
    trackingNode = ARImageNode(image: UIImage(named: "CowTracking"))
    
    // ノードの画像を正しい向きにするために回転
    trackingNode?.rotate(byDegrees: 90, axisX: 1.0, y: 0.0, z: 0.0)
    trackingNode?.rotate(byDegrees: 180.0, axisX: 0.0, y: 1.0, z: 0.0)
    trackingNode?.rotate(byDegrees: 90.0, axisX: 0.0, y: 0.0, z: 1.0)
    
    
}

普通に表示すると変な向きになってしまったのでちゃんと見えるように回転させてます。

マーカーレスのトラックを設定する setupArbiTrack() メソッドを追加します。次のようなコードを上記 addTrackingNode() メソッドの下に追加します。

func setupArbiTrack() {
    
    // ArbiTrack を初期化
    let arbiTrack = ARArbiTrackerManager.getInstance()
    arbiTrack?.initialise()
    
    // ジャイロマネージャーを初期化
    let gyroPlaceManager = ARGyroPlaceManager.getInstance()
    gyroPlaceManager?.initialise()
    
     // ターゲットとして使うノードを用意
    let targetImageNode = ARImageNode(image: UIImage(named: "CowTarget"))
    
    // デバイスのジャイロでノードが動くようにノードを ARGyroPlaceManager に追加
    gyroPlaceManager?.world.addChild(targetImageNode);
    
    // ノードの画像を正しい向きにするために回転し、サイズを調整
    targetImageNode?.rotate(byDegrees: 90.0, axisX: 1.0, y: 0.0, z: 0.0)
    targetImageNode?.rotate(byDegrees: 180.0, axisX: 0.0, y: 1.0, z: 0.0)
    targetImageNode?.rotate(byDegrees: 90.0, axisX: 0.0, y: 0.0, z: 1.0)

    targetImageNode?.scale(byUniform: 0.3)
    
    // ARArbiTrack の targetNode に指定
    arbiTrack?.targetNode = targetImageNode
    
    // ARArbiTracker の world に trackingNode を追加
    arbiTrack?.world.addChild(trackingNode)
}

Kudan AR SDK のマーカーレスモードではスマホのジャイロを使用するため、ARGyroPlaceManager のインスタンスを初期化し、後はマーカーモードと同じように targetNodeworldaddChild() すれば OK です。

setupContent() に上記 2つの呼び出しを追加

次に 2つのメソッドを呼び出しましょう。

override func setupContent() {
    
    addTrackingNode()
    setupArbiTrack()
}

ボタンの TouchUpInside イベントを追加

最後に、ボタンをクリックする度に、ARArbiTrackisTracking をチェックして startstop を切り替える以下のコードを追加します。

@IBAction func changeTrackingModeButton_TouchUpInside(_ sender: Any) {
    
    let arbiTrack = ARArbiTrackerManager.getInstance()
    
    if let arbiTracker = arbiTrack {
        if (arbiTracker.isTracking) {
            arbiTracker.stop()
            arbiTracker.targetNode.visible = true
            
            changeTrackingModeButton.setTitle("Start Tracking", for: UIControlState.normal)
        } else {
            arbiTracker.start()
            arbiTracker.targetNode.visible = false
            
            changeTrackingModeButton.setTitle("Stop Tracking", for: UIControlState.normal)
        }
    }
}

最終的な ArbiViewController クラスは次のようになっているはずです。

class ArbiViewController: ARCameraViewController {
    
    var trackingNode:ARImageNode?
    
    @IBOutlet weak var changeTrackingModeButton: UIButton!
    
    @IBAction func changeTrackingModeButton_TouchUpInside(_ sender: Any) {
        
        let arbiTrack = ARArbiTrackerManager.getInstance()
        
        if let arbiTracker = arbiTrack {
            if (arbiTracker.isTracking) {
                arbiTracker.stop()
                arbiTracker.targetNode.visible = true
                
                changeTrackingModeButton.setTitle("Start Tracking", for: UIControlState.normal)
            } else {
                arbiTracker.start()
                arbiTracker.targetNode.visible = false
                
                changeTrackingModeButton.setTitle("Stop Tracking", for: UIControlState.normal)
            }
        }
    }
    
    override func setupContent() {
        
        addTrackingNode()
        setupArbiTrack()
    }
    
    
    func addTrackingNode() {
        
        // トラッキング(表示)するノードを用意
        trackingNode = ARImageNode(image: UIImage(named: "CowTracking"))
        
        // ノードの画像を正しい向きにするために回転
        trackingNode?.rotate(byDegrees: 90, axisX: 1.0, y: 0.0, z: 0.0)
        trackingNode?.rotate(byDegrees: 180.0, axisX: 0.0, y: 1.0, z: 0.0)
        trackingNode?.rotate(byDegrees: 90.0, axisX: 0.0, y: 0.0, z: 1.0)
    }
    
    func setupArbiTrack() {
        
        // ArbiTrack を初期化
        let arbiTrack = ARArbiTrackerManager.getInstance()
        arbiTrack?.initialise()
        
        // ジャイロマネージャーを初期化
        let gyroPlaceManager = ARGyroPlaceManager.getInstance()
        gyroPlaceManager?.initialise()
        
         // ターゲットとして使うノードを用意
        let targetImageNode = ARImageNode(image: UIImage(named: "CowTarget"))
        
        // デバイスのジャイロでノードが動くようにノードを ARGyroPlaceManager に追加
        gyroPlaceManager?.world.addChild(targetImageNode);
        
        // ノードの画像を正しい向きにするために回転し、サイズを調整
        targetImageNode?.rotate(byDegrees: 90.0, axisX: 1.0, y: 0.0, z: 0.0)
        targetImageNode?.rotate(byDegrees: 180.0, axisX: 0.0, y: 1.0, z: 0.0)
        targetImageNode?.rotate(byDegrees: 90.0, axisX: 0.0, y: 0.0, z: 1.0)

        targetImageNode?.scale(byUniform: 0.3)
        
        // ARArbiTrack の targetNode に指定
        arbiTrack?.targetNode = targetImageNode
        
        // ARArbiTracker の world に trackingNode を追加
        arbiTrack?.world.addChild(trackingNode)
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

ビルドして動かしてみましょう。

こんな感じです!一度配置したら割とピタッと配置されますね。

https://platform.twitter.com/widgets.js

この後は

次はマーカーモードと同じく、マーカーレスで 3D モデルを配置することにチャレンジしてみたいと思います。

Kudan AR SDK エントリー一覧

Kudan AR SDK チュートリアル記事まとめ | エクセルソフト ブログ

をご覧ください。

以上です。

タイトルとURLをコピーしました