2018年6月15日金曜日

AR画面にSpriteを表示したい

Xcode9のARのテンプレートに用意されてるが、それを学習する。
ARもSpriteもよくわかってないので、時々トンチンカンかもしれませんよ。

使用ファイル


  • Scene.sks
    • Spriteを表示するための場所。Viewみたいなものだろ。場所として持ってるだけで、InterfaceBuilder的には何も設定されてないっぽい。
  • Scene.swift
    • Scene.sksに結びついてるクラス
    • 表示されたSceneがtouchされたらどうのこうの…という処理をしてるようだ
  • ViewController.swift
    • Scene.sksをロードして表示する
    • AR画面にSpriteを表示するためのARSKViewのdelegateメソッドで実際にSprite(ここではLabelNodeで👾)を表示してる

Scene.swift

touchしたらカメラの向いた方向の、カメラ位置の20cm先にARAnchorを追加する。

ARAnchorとは

ARシーンにオブジェクトを配置するために使用する、実世界の位置と方向の情報。
カメラに対する実オブジェクトまたは仮想オブジェクトの位置と向きを追跡するには、アンカーオブジェクトを作成し、add(anchor :)メソッドを使用してそれらをARセッションに追加する。
ARKitは、ワールドトラッキングセッションでplaneDetection(平面探索)オプションを有効にすると、アンカーも自動的に追加される。
ARAnchorを追加すれば、カメラの向きを変えたり、近づいたり離れたりしても、その空間上の位置を覚えててくれるわけですな。それによってそこに配置したSpriteに近づいたり離れたりできるわけだ。

ViewController

Scene.sksをロードし、ARSKViewに表示。
ARSKViewにdelegateが設定されており、SceneがtouchされてScene.swiftで新しいanchorが追加されると、ViewControllerに書かれた以下のdelegateメソッドが呼ばれ、anchor位置に👾のSpriteを表示する。

以下のARSKViewのdelegateメソッドが新しいanchorが追加されたら呼ばれるもの
func view(_ view: ARSKView, nodeFor anchor: ARAnchor) -> SKNode? { }
デリゲートに、新たに追加されたアンカーに対応するSpriteKitノードを提供するように要求します。
LabelNodeを作り、それをreturnしてるので、追加されたanchorの位置に表示している

任意の位置に表示させたい

Scene.swiftのtouchBegan()ではカメラを向けた方角の前方(設定では0.2m)に👾を表示させるべくARAnchorを追加している。
ARAnchorは4*4の行列で表されており、カメラを向けた位置の値(currentFrame.camera.transform)を別に用意した行列の変数(translation)と計算して変更している。
translationは行列の3列目のzの値に-0.2を設定し、カメラ位置の情報と演算することで前方0.2mのAnchor位置を設定している。
同じく以下のようにx,yの値を変更すれば、3次元空間上のAnchor位置を変更できる。なぜか横軸がy、縦軸がxっぽいのが納得いかないが。

AR開始時のカメラ(デバイス)の向きを基準に、以下のような意味になるようだ。

  • zは+が背後、-が前方
  • xは+が下、-が上方向
  • yは+が右手、-が左手

以下のように3列目のx,y,zを変更すれば、ある程度自由な位置に表示できる。

if let currentFrame = sceneView.session.currentFrame {
    var translation = matrix_identity_float4x4 //世界座標と向きを表す4*4の行列
    //zが奥行きの軸はいいとして、xが横軸、yが縦軸と思いきや、xが縦、yが横みたい?
    translation.columns.3.z = -0.2 //奥行き(前方0.2m)
    translation.columns.3.x = -1.0 //縦軸(上方1.0m)
    translation.columns.3.y = 0.5 //横軸(右手0.5m)
    //これは南を向いてデバイスを水平に構えた時の行列の値
    var transform = matrix_float4x4([0.0237875, -0.9977, 0.0634782, 0.0], [0.999125, 0.02154, -0.035859, 0.0], [0.0344092, 0.0642756, 0.997339, 0.0], [-0.000370748, -0.114079, -0.340914, 1.0])
    //南向き水平の値に対し、x,y,zの値を演算して変更している
    transform = simd_mul(transform, translation)

    //セッションに新しいARアンカーを追加
    let anchor = ARAnchor(transform: transform) //アンカーを作成
    sceneView.session.add(anchor: anchor) //sceneViewのsessionにアンカー追加
    //これによってViewControllerのdelegateが呼ばれる

}

0 件のコメント:

コメントを投稿