こんにちは。エクセルソフトの田淵です。
弊社取り扱いの Kudan AR SDK のエントリーです。
SDK のダウンロードは こちら からお申込みください。SDK を使った開発と、個人開発者のリリースは無料でご利用いただけます。企業の方は有料になりますので、@ytabuchi までご連絡ください。
前回の iOS のエントリー ではマーカー上で画像を表示しました。
今回は 3D モデルを表示します。基本的には Android と同じ流れで、画面を作り、コードを追記していきます。
現時点でのサンプルコードは ytabuchi の Github にアップしてあります。この後もコミット追加していくのでスナップショットです。
Asset の準備
最初に 3D モデルのモデルファイルとテクスチャーファイルをプロジェクトに読み込みます。
プロジェクトのルートを右クリックして、「New Group」をクリックし、「Assets」フォルダを作成します。
ダウンロードした
assets.zip
を展開し、ben.jet
をben.armodel
に拡張子を変更します。
(ben.jet
のままでも動作します。逆に、Android では.jet
の拡張子の必要があるようです。)拡張子が見えていない場合は macOS Sierra: ファイル名拡張子を表示する/隠す を参考に見えるようにしておくと何かと便利です。
ben.armodel
と bigBenTexture.png
を作成した Assets
フォルダにドラッグ&ドロップします。
コピーするかを聞かれますので、「add to targets」にチェックが入っていることを確認し、プロジェクトにコピーします。
Type が、ben.armodel
は「Default – Data」、bigBenTexture.png
は「Default – PNG Image」になっていて、「Target Membership」にチェックが入っていることを確認してください。
これでコードから参照できる状態になりました。
UI の設定
Storyboard にボタンを配置します。
詳細は割愛しますが、Constraints などを設定し、Option
キーを押しながら ViewController.swift
を開き、Outlet
と Action
を設定しておきましょう。
@IBOutlet weak var clearButton: UIButton! @IBOutlet weak var imageButton: UIButton! @IBOutlet weak var modelButton: UIButton! @IBAction func clearButton_TouchUpInside(_ sender: Any) { } @IBAction func imageButton_TouchUpInside(_ sender: Any) { } @IBAction func modelButton_TouchUpInside(_ sender: Any) { }
コード(ViewController.swift)の編集
setupContent の内容を分解
最初に複数のメソッドからアクセスされるクラス変数 var imageTrackable:ARImageTrackable?
を Action
の下、setupContent
の上に定義します。
setupImageTrackable
を用意して ImageTrackable
にマーカーを追加するコードを移動します。
func setupImageTrackable() { // ARImageTrackable オブジェクトのインスタンス化と初期化 imageTrackable = ARImageTrackable.init(image: UIImage(named: "lego.jpg"), name: "lego") // image tracker manager のインスタンスを取得して初期化 let imageTrackerManager = ARImageTrackerManager.getInstance() imageTrackerManager?.initialise() // ARImageTrackable を image tracker manager に追加 imageTrackerManager?.addTrackable(imageTrackable) }
次に addImageNode
を用意して、画像のオブジェクトを追加するコードを移動します。
func addImageNode() { // ImageNode を表示させたい画像で初期化 // PNG の場合は拡張子は不要です。 let imageNode = ARImageNode(image: UIImage(named: "cow")) // ARImageTrackable に imageNode を追加 imageTrackable?.world.addChild(imageNode) // マーカー画像のサイズに合わせるように、それぞれの幅から拡大率を計算 let scaleRatio = Float(imageTrackable!.width)/Float(imageNode!.texture.width) // 拡大率を ImageNode に適用 imageNode?.scale(byUniform: scaleRatio) imageNode?.visible = false }
その下に clearButton の TouchUpInside のアクションで呼ばれる、全てのノードを非表示にする clearAllNodes
メソッドを用意して、以下のコードを追加します。
func clearAllNodes() { let nodes = imageTrackable?.world.children nodes?.forEach({ (node) in node.visible = false }) }
メソッドが用意できたので、ボタンのアクションに追加しましょう。以下のコードを Action に追加します。
@IBAction func clearButton_TouchUpInside(_ sender: Any) { clearAllNodes() } @IBAction func imageButton_TouchUpInside(_ sender: Any) { clearAllNodes() imageTrackable?.world.children[0].visible = true }
この時点で動かしてみましょう。
ボタンでオブジェクトの表示を制御。良い感じ #Kudan ARです。 pic.twitter.com/hEuTxFH0L5
— 田淵 義人@エクセルソフト (@ytabuchi) 2018年8月20日
こんな感じです。良い感じですね!
3D モデルの処理を追加
ViewController.swift
に戻り、clearAllNodes
メソッドの前に、addModelNode
メソッドを追加します。
func addModelNode() { // モデルのインポート let modelImporter = ARModelImporter(bundled: "ben.armodel") let modelNode = modelImporter?.getNode() // モデルの ARMeshNode にアンビエントライトを適用 if let meshNodes = modelNode?.meshNodes { for case let meshNode as ARMeshNode in meshNodes { let material = meshNode.material as? ARLightMaterial material?.ambient.value = ARVector3(valuesX: 0.8, y: 0.8, z: 0.8) } } // 向きと拡大率を指定 modelNode?.rotate(byDegrees: 90, axisX: 1, y: 0, z: 0) modelNode?.scale(byUniform: 0.25) // ARImageTrackable に modelNode を追加 imageTrackable?.world.addChild(modelNode) modelNode?.visible = false }
ARModelNode
クラスのメッシュオブジェクトが格納されている meshNodes
は [Any]? 型なのでアンラップして ARMeshNode
のオブジェクトの material
に割り当てています。
Android ではモデルファイルとテクスチャーファイルを指定していましたが、このコードでは、
ARLightMaterial
を使用していルため、モデルファイルに含まれる(?)テクスチャーのファイル名を自動的に参照してくれるようです。そのため、コード内ではbigBenTexture.png
を参照していません。現時点で私が Material についてあまり知識を持っていないのでまだよく分かっていませんが、理解できたらこのエントリーも更新したいと思います。
最後にボタンの TouchUpInside イベントにコードを追加しましょう。
@IBAction func modelButton_TouchUpInside(_ sender: Any) { clearAllNodes() imageTrackable?.world.children[1].visible = true }
最終的に ViewController.swift
は以下のようになっているはずです。
import UIKit import KudanAR class ViewController: ARCameraViewController { @IBOutlet weak var clearButton: UIButton! @IBOutlet weak var imageButton: UIButton! @IBOutlet weak var modelButton: UIButton! @IBAction func clearButton_TouchUpInside(_ sender: Any) { clearAllNodes() } @IBAction func imageButton_TouchUpInside(_ sender: Any) { clearAllNodes() imageTrackable?.world.children[0].visible = true } @IBAction func modelButton_TouchUpInside(_ sender: Any) { clearAllNodes() imageTrackable?.world.children[1].visible = true } var imageTrackable:ARImageTrackable? override func setupContent() { setupImageTrackable() addImageNode() addModelNode() } func setupImageTrackable() { // ARImageTrackable オブジェクトのインスタンス化と初期化 imageTrackable = ARImageTrackable.init(image: UIImage(named: "lego.jpg"), name: "lego") // image tracker manager のインスタンスを取得して初期化 let imageTrackerManager = ARImageTrackerManager.getInstance() imageTrackerManager?.initialise() // ARImageTrackable を image tracker manager に追加 imageTrackerManager?.addTrackable(imageTrackable) } func addImageNode() { // ImageNode を表示させたい画像で初期化 // PNG の場合は拡張子は不要です。 let imageNode = ARImageNode(image: UIImage(named: "cow")) // マーカー画像のサイズに合わせるように、それぞれの幅から拡大率を計算 let scaleRatio = Float(imageTrackable!.width)/Float(imageNode!.texture.width) // 拡大率を ImageNode に適用 imageNode?.scale(byUniform: scaleRatio) // ARImageTrackable に imageNode を追加 imageTrackable?.world.addChild(imageNode) imageNode?.visible = false } func addModelNode() { // モデルのインポート let modelImporter = ARModelImporter(bundled: "ben.armodel") let modelNode = modelImporter?.getNode() // モデルの ARMeshNode にアンビエントライトを適用 if let meshNodes = modelNode?.meshNodes { for case let meshNode as ARMeshNode in meshNodes { let material = meshNode.material as? ARLightMaterial material?.ambient.value = ARVector3(valuesX: 0.8, y: 0.8, z: 0.8) } } // 向きと拡大率を指定 modelNode?.rotate(byDegrees: 90, axisX: 1, y: 0, z: 0) modelNode?.scale(byUniform: 0.25) // ARImageTrackable に modelNode を追加 imageTrackable?.world.addChild(modelNode) modelNode?.visible = false } func clearAllNodes() { let nodes = imageTrackable?.world.children nodes?.forEach({ (node) in node.visible = false }) } 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. } }
「3D Model」ボタンをクリックして、以下のようにマーカー上に時計台が表示されれば成功です。
この後は
次は動画を表示してみましょう。
Kudan AR SDK エントリー一覧
Kudan AR SDK チュートリアル記事まとめ | エクセルソフト ブログ
をご覧ください。
以上です。