非ゲーム系アプリの開発が中心だと、3Dオブジェクトを取り扱う事がほとんどないので、3Dゲーム開発用のフレームワークであるSceneKitを利用する機会がありません。

しかし現在リサーチしている、ARKitを使いこなすには、SceneKitの理解は必須です。なぜならARKitが現実世界の検出したあとの3DオブジェクトのハンドリングはSceneKitが担当するからです。

 2次元世界であるUIKitの文化圏と大分異なるSceanKitですが、しっかり理解していきたいと思います。

2次元 → 3次元への入り口

3次元を表現するために、2次元では存在しない概念が出てきます。
下記の様な要素によって3次元の世界は構成されます。
 
  • シーン(空間)
  • オブジェクト(物体)
  • ライト(照明)
  • カメラ

x軸、y軸だけでなく、奥行きとしてz軸が存在します。

ref.Apple公式より転載
 

SceanKitの基本的な構成と流れ

  • 大元となるSCNViewのsceanプロパティにSCNSceneのオブジェクト(scene)を設定
  • SCNNodeに、3Dモデルや、カメラ、ライトなどを設定
  • sceneのrootNodeに、childNodeとして各ノードを追加

シーンを設定

3Dモデルノードを追加

まずSCNGeometryでジオメトリを生成。SCNGeometryは箱型、球体、円柱など様々な形があります。
ジオメトリには、色やテクスチャもマテリアルとして設定可能です。

SCNNodeのgeometryプロパティにジオメトリを代入して、ノードを生成。
ノードにpostion、nameを設定する。

このpositionの設定が、3次元慣れしていないとややこしい…。

箱型ノードの設定

箱型ジオメトリを代入したノードに、文字列ジオメトリを代入したノードを追加します。
文字列を画面中央に配置するために、positonも調整します。最後に文字列ノードがぶら下がった、箱型ノードをroodNodeに追加します。

文字列ノードの設定 +  rootNodeに箱型ノードを追加

※参考にさせていただいたサイト
https://dev.classmethod.jp/smartphone/ios-11-arkit-scntext-2/

カメラノードを追加

SCNCameraをSCNNodeのcameraプロパティに設定。カメラが全体を写せるように、positonのz軸を調整します。

ライトノードを追加

SCNLightをSCNNodeのlightプロパティに設定。こちらも、positonを調整して光の当て方を調整します。

各種光源タイプの詳細は、Apple公式を参照
https://developer.apple.com/documentation/scenekit/scnlight/lighttype

途中経過

インタラクションさせてみる

UITapGestureRecognizerでタップされた位置情報を取得し、SCNViewのhitTestメソッドでタップした位置にあるノードの情報を取得します。

もしヒットしたノードがboxノードであれば、タップする度にz軸を-10して奥に押し込まれる様なインタラクションを実現します。

hitTest
https://developer.apple.com/documentation/scenekit/scnscenerenderer/1522929-hittest

アニメーションさせてみる

CoreAnimationを利用して3Dオブジェクトにアニメーションをつける事も可能です。

CABasicAnimationのkeyPathに変化させたいノードのプロパティ(ここではposition)を指定して、fromValueとtoValueで変化をつけます。

アニメーションをつけたいノードにaddAnimationするだけでOK。

CABasicAnimation
https://developer.apple.com/documentation/quartzcore/cabasicanimation

これで箱型ノードのオブジェクトが迫ってくる様なアニメーションをつけれました。
ライトノードの位置は固定のままなので、ライトノードのz軸より手前に移動すると箱型ノードが照らされなくなっているのがわかります。