こんにちは。エクセルソフトの田淵です。
弊社取り扱いの Kudan AR SDK のエントリーです。
SDK のダウンロードは こちら からお申込みください。SDK を使った開発と、個人開発者のリリースは無料でご利用いただけます。企業の方は有料になりますので、@ytabuchi までご連絡ください。
前回の iOS のエントリーではマーカーの上に動画を表示させるところまでをやりました。
今回は遂にマーカレスです。
現時点でのサンプルコードは ytabuchi の Github にアップしてあります。この後もコミット追加していくのでスナップショットです。
作業の流れ
今までは Storyboard の最初の ViewController
で作業していたので、ビューを分けたいと思います。
こんな感じですね。
Main.Storyboard
を書き換えViewController.swift
をMarkerViewController.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
のインスタンスを初期化し、後はマーカーモードと同じように targetNode
と world
に addChild()
すれば OK です。
setupContent() に上記 2つの呼び出しを追加
次に 2つのメソッドを呼び出しましょう。
override func setupContent() { addTrackingNode() setupArbiTrack() }
ボタンの TouchUpInside イベントを追加
最後に、ボタンをクリックする度に、ARArbiTrack
の isTracking
をチェックして start
/stop
を切り替える以下のコードを追加します。
@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. } }
ビルドして動かしてみましょう。
こんな感じです!一度配置したら割とピタッと配置されますね。
Kudan AR SDK、iOSのマーカーレスです。 #Kudan pic.twitter.com/dCNgVUwRZ1
— 田淵 義人@エクセルソフト (@ytabuchi) 2018年10月11日
この後は
次はマーカーモードと同じく、マーカーレスで 3D モデルを配置することにチャレンジしてみたいと思います。
Kudan AR SDK エントリー一覧
Kudan AR SDK チュートリアル記事まとめ | エクセルソフト ブログ
をご覧ください。
以上です。