見出し画像

Lesson 3A.2 Introduction to SceneKit

前のレッスンでは、拡張現実アプリのテンプレートが船のシーンを提供することを学びました。もちろん、独自のARアプリを作成する際には、他の3Dモデルを使用したいと思うでしょう。このレッスンでは、SceneKitで利用可能な基本的な3Dオブジェクト、拡張現実シーンに追加する方法、およびそれらを互いに関連して配置する方法について学びます。

あなたが学ぶこと

SceneKitオブジェクトの追加方法とシーン内配置方法

独自のSceneKitファイルを作成して読み込む方法

SceneKitオブジェクトをプログラムおよび視覚的に作成する方法

基本的な照明をあらゆるシーンに適用する方法

Vocabulary
depth fighting 
scene hierarchy
SCNLight
SCNNode
SCNVector

p.454 
SceneKitオブジェクト

3Dでの作業には、空間内のオブジェクトの位置決めが含まれます。SceneKitは、シーン階層内の一連のノードとして世界を整理し、各ノードは3D空間内のオブジェクトを表します。コードを書くときは、SCNSceneクラスとSCNNodeクラスのインスタンスを使用してシーンを管理します。各SCNNodeには、その形状(またはジオメトリ)、照明情報、他のノードとの関係などの他のプロパティとともに、3D空間内の位置があります。

UIKitを使用する以前のレッスンから思い出すように、ユーザーが見るすべてのビジュアル要素(またはビュー)は、もともとUIViewから継承しています。ビューを表示するには、x/yの位置、幅、高さの3つの情報が必要です。一緒に、これらのデータはビューのフレームを形成します。たとえば、次の画像では、オレンジ色の長方形は右に20ピクセル、下に40ピクセル配置され、幅は320、高さは60です。したがって、フレームプロパティの値は(20、40、320、60)です。

p.455 
オレンジ色の長方形にサブビューとしてフレーム値(0、0、60、60)の青い正方形を追加すると、どこに表示されますか?最初は、青い四角が画面の左上隅に表示されると思うかもしれませんが、代わりに元のオレンジ色の長方形の左上隅にあります。これは、(0,0)x/y位置が親ビューからの相対値であるためです。

SceneKitは、同様の方法でノードを配置します。2Dではなく3Dでのみ配置します。ARKitアプリには、showWorldOriginデバッグオプションを有効にすることで、レッスン1で見た位置にワールドオリジン(0,0,0)があります。世界の原点を基準にしてノードを配置できます

p.456 
または、ビューやサブビューと同様に、他のノードの位置を基準にしています。相対位置決めでは、最上位ノードの位置が変更された場合、子ノードはそれに従います。拡張現実アプリテンプレートのship.scnファイルでは、shipノードはトップレベルのノードであり、shipMeshは唯一の子ノードです。

SceneKitでは、UIViewのサブクラスを画面に追加するのではなく、SCNNodeオブジェクトで表されるシーン階層にノードを追加します。SCNNodeは、要素の位置、その形状(またはジオメトリ)、照明情報など、3D空間の要素を記述します。

しかし、ノードは必ずしもユーザーが見るものである必要はありません。それは単に位置を表し、3Dの世界を見るための「カメラ」として機能します。たとえば、カメラを3Dオブジェクトの上に配置されたSCNNodeに切り替えることで、オブジェクトの正面図から鳥瞰図に切り替えることができます。ARKitと組み合わせて使用すると、デバイスがカメラであるため、SceneKitのカメラノードはほとんど使用されません。

シーンの作成

独自のシーンを作成する方法を学びながら、学校のキャンパスのシーンをまとめます。キャンパスの一部を視覚的に構築し、プログラムで他の人を構築します。経験を積むにつれて、どの方法でシーンを作成するかを決定し、一方の方法を使用する理由を発見します。

拡張現実アプリのテンプレートを使用して新しいプロジェクトを作成し、プロジェクトに「SceneKit-Primitives」という名前を付けます。(必要に応じて、このレッスンでは使用しないため、ship.scnファイルとtexture.pngファイルを削除できます。)独自のシーンを作成するには、プロジェクトナビゲーターでart.scnassetsフォルダを右クリックし、[新規ファイル]を選択して.scnファイルの名前をcampupcampupnに変更します。シーンには、シーングラフ内に1つのカメラノードが含まれています。ゼロから始めるには、ノードを削除してください。

ViewController定義のviewDidLoad()メソッドに移動し、ワールドオリジンを有効にしながら、新しいシーンファイルを読み込むコードを変更します。

p457 
ノードの追加

オブジェクトライブラリを開いて、ノード、照明、幾何学的形状などのオブジェクトのリストを見つけます。これは、シーングラフに追加できます。

オブジェクトライブラリの「空のノード」を見つけて、シーングラフビューにドラッグします。ノードインスペクタの下 ノードに「キャンパス」という名前を付けます。これは、シーンの多くの部分を配置するために使用するトップレベルのノードです。

p.459 
コードを使用してシーンにSCNNodeを追加するとどうなりますか?実際、既存のビューにUIViewを追加するのとよく似ています。まず、デフォルトの初期化子SCNNode()でオブジェクトを初期化し、ノードに位置を与えます。もちろん、3Dでは、x/yの位置では不十分です。ノードの位置プロパティはSCNVector3型で、初期化子はx、y、zの3つのパラメータを使用します。デフォルトでは、値は(0.0、0.0、0.0)です。しかし、この例では、世界原点から0.2メートル上に位置するノードを作成します。そのコードは次のとおりです。

ビューとは異なり、ノードはサブビューとして追加されず、既存のノードに子ノードとして追加されます。シーンには、原点(0,0,0)から始まるrootNodeプロパティが含まれています。addChildNodeメソッドを使用すると、このノードを使用して新しいノードのアタッチを開始できます。

sceneView.scene.rootNode.addChildNode(node)

今、あなたはノードを持っていますが、どのようにそれを見えるようにしますか?図形と色を追加するには、ジオメトリ値をSCNGeometryオブジェクトに割り当てることができます。しかし、空のノードを変更するのではなく、Interface Builderを使用してオブジェクトライブラリから図形を追加する方が簡単です。

基本的なジオメトリタイプ

SceneKitは、シーンで使用できる基本的な図形を多数提供します。これらの形状はすべてSCNGeometryのサブクラスであり、色や使用される材料(照明に影響を与える)など、モデルとその関連値が含まれています。



ボックス、または3Dキューブは、SCNBoxクラスを使用して作成された基本的な長方形です。長さ、幅、高さがあり、角を丸めるために使用できる半径があります。

校舎を表すには、オブジェクトライブラリで「ボックス」を見つけて、先ほど作成したキャンパスノードに子ノードとして追加します。

p.460 
ボックスに「本館」という名前を付け、材料検査官で茶色に着色します。

翻訳できず

p461 
これをコードで実行している場合は、次のようになります。

アプリを構築して実行すると、メインの建物が見えますか?おそらく、茶色の箱だけが見えます。なぜなら、それはとても大きく、原点の真上に配置されているからです。箱を小さくするには、長さ、幅、高さを調整できます。しかし、より簡単な方法は、ノードインスペクタのscaleプロパティを使用して、全体的なサイズパーセンテージを調整することです。

軸に0.5のスケールを適用し、位置のz値を-1に設定します。これで、ARシーンには合理的なサイズと位置の建物があるはずです。うまくいく値が見つかるまで、これらの数字で遊んでください。サイズと色を試してみてください。SceneKitエディタでもコードでも、数字を調整できます。

p462.
彼らは後で、あなたのシーンで何かを壊すことを心配しないでください。シーンに図形を追加する際には、それらがすでにスケーリングされているノードの子ノードであることを確認してください。そうすれば、キャンパスシーンのサイズを調整するたびに個別にスケーリングする必要はありません。

参考までに、コードを使用してloadMainBuilding()に同じ調整を行う方法は次のとおりです。

水準

平面は、SCNPlaneクラスで表される平らな面です。平面には2次元しかないので、斜めでしか見ることはできません。色と組み合わせて、飛行機を使って歩道や芝生を作ることができます。

まず、オブジェクトライブラリから「プレーン」を見つけ、メインビルディングノードに子ノードとして追加し、「歩道」という名前を付けます。幅3.5、高さ1.5、または作成したボックスより少し大きい値を指定してください。そうすれば、歩道は建物の向こうに伸びます。

しかし、あなたはすぐに問題に気づくでしょう:飛行機は平らに横たわるのではなく、建物の後ろに垂直に立っています。

p.463
デフォルトでは、平面のwidthプロパティはx軸で拡張され、heightプロパティはy軸で拡張されます。しかし、水平歩道を作成するには、平面はx軸とz軸に沿って増加している必要があります。最も簡単な解決策は、ノードインスペクタのオイラープロパティを変更することで、x軸に沿って平面を90度回転させることです。(回転するための正しい軸はすぐに直感的ではないかもしれません。ローテーションと変革を理解するには、練習が必要です。

p464 
歩道に灰色を与え、建物のあらゆる側面に同じ幅の歩道があるようにサイズを調整します。

コードでシーンを作成する場合は、次のようになります。( isDoubleSided プロパティは true に設定されており、上から見ても下から見ても、平面が見えるようにしてください。SceneKitエディタを使用してシーンに平面を導入すると、そのプロパティはすでにtrueに設定されています。

eulerAnglesプロパティを設定する代わりに、x値を変更することです。360度は2 * πに等しいので、90度はπ/2に等しい。

p.465 
本館の下に2番目の大きな飛行機を追加します。芝生を表す緑色にしてください。好きなだけ草ができるまで値を調整しますが、注意してください。歩道と草の平面が同じy値の場合、わずかに重なり、グラフィカルなバグが発生する可能性があります。この問題は深度の戦いと呼ばれ、SceneKitはシーン内で同じ深さを持つオブジェクトをレンダリングする方法を決定できません。

SceneKitは、深度の戦いを解決するための複数の方法を提供します。最も簡単な解決策は、芝生のy値を歩道より少し低い値に設定することです。次の画像では、歩道面のy値は-0.5、芝生面は-0.501です。

p.466 .
円筒

シリンダーは、ある程度の材料で結ばれた2つの平行円で構成されています。SCNCylinder初期化子は、円の両方に半径、それらの間のスペースに高さを必要とします。

キャンパスシーンでは、シリンダーを使用して木の幹を作成できます。他の図形と同様に、オブジェクトライブラリで「シリンダー」を見つけて茶色に設定します。

p.467 
球体


最後に必要な物体は球体です。SCNSphereクラスで表される球体は半径のみを必要とします。

球体を使用して、木の幹シリンダーの緑豊かな王冠を作成できます。しかし、このノードをルートノードの子として追加するのではなく(他の図形と同じように)、ツリーのクラウンはトランクなしでは存在しないため、トランクノードの子として追加する必要があります。

p.469 
照明

キャンパスシーンに置いた形は少し...鈍く見えますか?それらは特定の角度で平らに見えるかもしれませんし、3Dでそれらを知覚するために動き回らなければならないかもしれません。これは球体では特に明白です。エッジがないため、視野角に関係なく円のように見えます。

ご覧のとおり、照明はオブジェクトを3次元的に見せるための鍵であり、SceneKitはシーンに照明を導入する無数の方法を提供します。オブジェクトライブラリから、ノードにさまざまな種類のライトを追加できます。また、Materialsインスペクタを使用すると、光がオブジェクトとどのように相互作用するかを正確に指定できます。実際、オブジェクトの色やテクスチャを設定するために使用する拡散プロパティは、オブジェクトが光にどのように反応するかを指定する方法の1つです。

シーンの外観を大幅に向上させる最も簡単な方法は、シーンビューのautoenablesDefaultLightingプロパティをtrueに設定することです。これにより、既存のすべてのノードと相互作用する全方向性光源がシーンに配置されます。

演習

Xcodeのドキュメントを使用して、SCNConeクラスを調査します。次に、本館とは別に、SCNConeを屋根として使用する新しい建物を作成します。

loadTree()関数を変更して、ツリーのx/z位置の2つの追加パラメータを取ります。次に、ループを使用して、校舎の周りに木の列を作成します。

自分の学校のキャンパスによく似た新しいシーンを作成します。


この記事が気に入ったらサポートをしてみませんか?