SceneKitでプリミティブなジオメトリから3Dモデルを作ろう


先日作成したARKitのサンプルコード集ARKit-Emperorの中に、額縁の中に画像を入れて平面に置くというサンプルコードがあります。

この額縁はXcode上で、SceneKitで作成しました。

この額縁の作り方を紹介していきたいと思います。

完成品


https://github.com/kboy-silvergym/ARKit-Emperor/blob/master/ARKit-Emperor/art.scnassets/pictureTable.scn

構造

  • sideBoxという名前の四角柱が4本
  • legという名前の脚が1本
  • (おまけにspotという名前のスポットライト)

順をおって作り方を解説していきます。

作り方

sideBoxを作ろう

art.scnassetsフォルダのところで新規ファイルを作るとSceneKit Scene.scnという名前でscnファイルが作られます。

今回はこれをpictureTable2という名前にして進めていきます。

まずはBoxをおく

Xcode10では、右上の□ボタンみたいなところを押すと、以下のようにnodeやlight、プリミティブ(基本的)なジオメトリが選択できます。

今回は、Boxを選択します。これをドラッグアンドドロップで、sceneに持って行ってください。

ドラッグアンドドロップすると以下のように表示されます。マウスでドラッグすることで角度を変えることができて、右クリック(macのトラックパッド2本指)で平行移動できます。

Boxの大きさを調整していく

このBoxを選択した状態で、右側のattribute inspectorを選択すると、Sizeという項目が現れます。ここを変更して、細長い円柱を作っていきましょう。

僕のサンプルでは、

  • width 0.03
  • height 0.53
  • length 0.03

にしているので、同じように調整してみましょう。ちなみに単位はm(メートル)なので、0.03は3cm、0.53は53cmです。

色をつけよう

boxを選択したまま、今度はmaterialのタブを選択します。

shadingは質感を示していて、diffuseの部分で色を選択できます。また、diffuseには画像もしているすることができます。

(AppEngineというブログがとても詳しいので気になる方は読んでみてください。)

4本に増やそう

Scene graghでコピーアンドペーストすると、増やすことができます。

移動、回転させてみよう

ただ、この状態はまだ全て同じポジションにあって重なっていますので、一本ずつずらしてみましょう。

x、y, z軸を選択しながらドラッグすると平行移動できます。

ちなみに角度の部分を選択しながらドラッグすると回転もできます。

4本のboxをグループ化

まず、emptyNodeをscene graphに追加します。

適当な名前をつけます。

4本のboxをドラックアンドドロップでframeの配下に入れます。

4本のboxの座標や角度を調整する

これでboxたちはframeというnodeの配下に入ったので、frameのローカル座標系で座標を変更していくことになります。

今度は立方体マークのタブクリックして、transformのposition(座標)やeuler(角度)をいい感じに調整していきましょう。

そしたらこんな感じ。

脚は今回説明を省きます。これで完成!!

作ったモデルをコードで呼び出す

    lazy var pictureTableNode: SCNNode = {
        let scene = SCNScene(named: "art.scnassets/pictureTable.scn")!
        let node = scene.rootNode.childNode(withName: "tableNode", recursively: false)!
        node.name = "tablePictureNode"

        // 写真のnode
        let picture = SCNBox(width: 0.5, height: 0.5, length: 0.01, chamferRadius: 0)
        picture.firstMaterial?.diffuse.contents = #imageLiteral(resourceName: "kboy_profile")
        let pictureNode = SCNNode(geometry: picture)

        // frameに貼る
        let frameNode = node.childNode(withName: "frame", recursively: true)
        frameNode?.addChildNode(pictureNode)

        node.scale = SCNVector3(x: 0.3, y: 0.3, z: 0.3)
        return node
    }()

こんな感じで呼び出して、positionに気をつけて画像を貼ると、

このようなアウトプットになります。

ARKit-EmpelorのPictureViewControllerで再現しているので、コードはそちらを確認してみてください!