Help us understand the problem. What is going on with this article?

ARKitで立方体の6面それぞれに異なるテクスチャを貼る方法[追記あり]

はじめに

iOS11(beta)で登場したARKitで遊んでいます。ちょっとしたアイディアで面白いアプリができそうで楽しいです。

立方体の6面それぞれに別々のテクスチャを貼ろうとしたところ、検索しても明確な説明が見つからなかったので、簡単なコードを書いて実験してみました。

※この記事を描いてだいぶ経ってから、扱っている立体は〈立方体〉ではなく、〈直方体〉であることに気がつきました。タイトルまで変えると検索性が悪くなるので、本稿ではそのまま〈立方体〉で通しています。(2020/06/02 追記)

環境

  • Xcode Version 9.0 beta 3 (9M174d)
  • iOS11 beta 11.0(15A5341f)
  • iPhone 6S(MKQW2J/A)

座標系について

地面に垂直に立って、カメラを正面に向けてiPhoneを保持しているとします。

アプリ起動時のiPhoneの位置が原点となり、自分から見て、左→右方向がX軸の正の方向、下→上方向がY軸の正の方向となります。Z軸は正面→背面方向が正の方向となりますので、気をつける必要があります。

このときiPhoneが傾いていたとしても、地面に対して垂直・水平が基準となって座標系が設定されます。この座標系はアプリ起動後に設置され、その後iPhoneの位置が移動しても、原点の位置と軸の方向は維持されます(これがARの面白いところ)。

長さの単位ですが、コード上の1.0が現実世界の1mに対応します。

テクスチャの貼り方を試す

立方体の6面全てに同一のテクスチャを貼る場合は、以下のようにすれば済みます。

cube.firstMaterial?.diffuse.contents = UIImage(named: "texture.png")

6面それぞれに別のテクスチャを貼ろうとした場合は、ノードのmaterialsプロパティに、テクスチャの配列を与えれば良いのですが、順番や向きがどうなるのかよくわからなかったので、シンプルなプログラムを書いて実験してみます。

図のような6面分のテクスチャを用意しました。

six_textures_t.png

コード

幅10cm、高さ20cm、奥行き30cmの立方体を作成し、テクスチャを貼り付けます。辺の長さを変えているのは、面の対応関係がわかりやすいようにです。

GameScene.swift
    func makeCube() {
        // 幅10cm、高さ20cm、奥行き30cmの立方体を作成
        let cube = SCNBox(width: 0.1, height: 0.2, length: 0.3, chamferRadius: 0)
        let cubeNode = SCNNode(geometry: cube)

        // 6面、別々のテクスチャを貼る
        let m1 = SCNMaterial()
        let m2 = SCNMaterial()
        let m3 = SCNMaterial()
        let m4 = SCNMaterial()
        let m5 = SCNMaterial()
        let m6 = SCNMaterial()

        m1.diffuse.contents = UIImage(named: "texture_1.png")
        m2.diffuse.contents = UIImage(named: "texture_2.png")
        m3.diffuse.contents = UIImage(named: "texture_3.png")
        m4.diffuse.contents = UIImage(named: "texture_4.png")
        m5.diffuse.contents = UIImage(named: "texture_5.png")
        m6.diffuse.contents = UIImage(named: "texture_6.png")

        cube.materials = [m1, m2, m3, m4, m5, m6]

        // 初期位置の指定: 50cm画面奥、10cm上方に配置
        cubeNode.position = SCNVector3Make(0, 0.1, -0.5)

        self.rootNode.addChildNode(cubeNode)
    }

結果

このようにテクスチャが貼られます。

手前から見たとき、つまり原点側からZ軸マイナス方向に見たときの画像です。
IMG_0036.PNG

手前側で3つの線分が直交している点が原点で、赤がX軸、緑がY軸、青がZ軸です。
やや上から見下ろしているので、立方体は1,2,5の面が見えます。

奥から振り返って見たとき、つまりZ軸マイナス方向から原点方向を見たときの画像です。
IMG_0037.PNG

画面奥に原点があり、X軸、Y軸、Z軸が直交しています。
やや下から見上げているので、立方体は、3,4,6の面が見えます。

展開図にしてみるとこんな配置となります。

textures_development.png

おわりに

Qiitaに記事を書くのは初めてです。

初歩的な事ですが、自分がわからなかったことがわかったとき、それを共有することで、どこかの誰かに役立てば嬉しいことです。

ARKitはいじっていてわくわくします。簡単なアプリを作って、app storeで公開することを目標にしています。

surfinhamster
8080の機械語からプログラミングをはじめたので、やたら歴だけは長いけど素人プログラマー。少女時代のファン。
https://www.surfinhamster.net
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away