Apple Engine

Apple, iPhone, iOS, その周辺のことについて

iOS で SceneKit を試す(Swift 3) その33 - ジオメトリの質感を決めるマテリアルについて

SceneKit で言うマテリアルとはジオメトリの質感を決めるための設定だと考えてもらえば良いかと。
これまででも、firstMaterial などで設定していたがもう少し詳しくを紹介していく。

以前に、3DCG にはカメラ、ジオメトリ、ライトが必要だと書いたが、もう一つ重要なのがジオメトリの質感である。
大体の 3DCG の制作ツールなどでは最初に設定されているため、マテリアル設定がないということはないが、マテリアルが存在しないとジオメトリが描画されない。

 

マテリアルは何をしているのか

ジオメトリの法線情報を元に、ジオメトリがどのような色の光を反射しているか決めており、
赤い物体は赤色を反射するし、光が強いとハイライトができる。

 

f:id:x67x6fx74x6f:20170719141555p:plain

 

法線とは

ざっくり書くと、主な役目はジオメトリの頂点や面がどの方向を向いているかの情報。

f:id:x67x6fx74x6f:20170719141726p:plain

 

例えば、カメラやライトの光に対して表を見ているか裏を見ているか。 カメラから見て裏にあるものは、ものに隠れるので描画しなくても良いし、 ライトから見て裏にある部分は陰を落とす。

 

強引にジオメトリの断面を書いたが、
ライトが光を照射している方向の反対向きに法線がある場合はハイライトになるし、同じ向きに近い方は影になる。

f:id:x67x6fx74x6f:20170719141751p:plain

 

SceneKit のマテリアルの種類 (Lighting Model)

マテリアルでは 3DCG の制作ソフト同様に、
光の処理が異なるライティングモデルが用意されている。

ほとんどの場合 Physically Based を使用することが多いと思われる。

  • Constant
  • Lambert
  • Blinn
  • Phong
  • Physically Based

 

f:id:x67x6fx74x6f:20170719155448p:plain  

Constant

単色で塗られ光の影響を受けない。

 

Lambert

光沢のないつや消しを行なっている物体に向いている質感。
ハイライトはつかない。

 

Blinn

金属のような広めのハイライトをもつ物体に向いている質感。
2番目に計算のコストが高い。

 

Phong

鏡面反射を行うような物体のような強い光沢を持つ質感。
Normal や iOS 11 で追加される Height Map では、ロジク的な問題で状況によっては光沢部分が汚くなる可能性がある。

 

Physically Based

Lambert、Blinn、Phong は計算で近似した質感を計算しているが、
Physically Based は光学的に現実世界に近いリアルなジオメトリの表示を行う。 この中では最も計算コストが高い。

 

SceneKit マテリアルにはどのような設定値があるのか

以下のもの。ライティングモデルで使用できるものが異なる。

名称 機能
Diffuse 表面色の設定
Specular 光沢色の設定
Normal Normal Map 使用時の設定
Reflective 鏡面反射設定
Transparent 半透明時の設定(こちらとは別にジオメトリ全体のもある)
Occlusion Ambient Occlusion (画像)使用の際の設定
Illumimation 自発光しているように見せるための設定
Emission 自発光の値の設定
Multiply 全ての設定適応後にこちらの値が乗算される設定
Ambient 環境光の設定

 

ライティングモデルが Physically Based のみ使用できるもの。

名称 機能
Metalness 金属のような表面を表す設定
Roughness 表面の粗さの設定

 

Physically Based 以外では、フレネル効果(シャボン玉のように輪郭部分の屈折率が変わる効果)の追加ができ、
Blinn、Phong ではハイライトの設定を Shininess で設定できる。

 

共通で設定できるものでは、ジオメトリの半透明度やジオメトリをどのように描画するか、深度情報をどのように扱うかなどがある。

詳しくは Material Inspector の説明の際に紹介する。

 

テクスチャ

画像を壁紙やシールのようにマテリアルに貼り付けることができる。 マテリアルの色は Swift の Any となっており UIColor やテクスチャ、テクスチャの配列を設定できる。

テクスチャや色の設定をすることでジオメトリのリアリティが増す。

f:id:x67x6fx74x6f:20170719155424p:plain

 

今回はここまで。

iOS で SceneKit を試す(Swift 3) その33 - Scene Editor のジオメトリの Attribute Inspector

ビルトインジオメトリの設定値以外で、他の項目に触れていないため、もう少し見てみる。

 

概要

設定されているもの

  • ジオメトリの情報
  • モーフアニメーション用の設定
  • サブディビジョンサーフェイスの設定
  • ジオメトリのシェアリングの解除
  • ライト情報のベイク

 

f:id:x67x6fx74x6f:20170714161958p:plain

以下、各項目の説明

 

Geometry

Name はコードでこのジオメトリを使用する際、調べるためのもので、 Identifier は基本設定ができない。

Vertices はジオメトリの頂点数、
Polygons はポリゴン数でジオメトリの状態が確認できる。

 

Geometry Morphers

モーフアニメーション用で Scene Editor では編集ができない。

オブジェクトファイルなどのデータがある場合は、 アニメーションさせるターゲットが列挙される。

 

Geometry Sharing

Scene Editor の View や Scene Graph View でコピーされたジオメトリは、 必ずコピー元と情報が共有されて使用される。
(コードでいう clone() が実行されている状態)

そのため、Scene Editor でコピーしジオメトリ情報を変更を行うと
コピー元のジオメトリも変更されてしまう。

「Unshare」のボタンを押すと、情報が共有されなくなる。

 

Geometry Subdivision

サブディビジョンサーフェイスの設定。
Subdiv level でポリゴンの分割数を指定できる。

Scene Editor で行うことはできないが、
edgeCreasesElement と edgeCreasesSource でサブディビジョンサーフェイスの掛かり具合を設定できる。

 

Geometry Elements

前回、コードの方で設定していたもので面の状態を決める。

Scene Editor で設定不可。

 

Geometry Source

前回、コードの方で設定していたもので、 頂点の位置、頂点カラー、法線、タンジェント、テクスチャの UV 情報など設定できる。

Scene Editor で設定不可。

 

Baking

ライト情報をベイクするタイプは Ambient Occlusion と Light Map の2つあり、 頂点カラーとテクスチャーが選択できる。

設定値は Quality で、テクスチャーの場合は陰の Attenuation(減衰)が設定できる。

「Bake」ボタンを押すと焼き込み処理がされる。

 

何回が試しているが、テクスチャの方のベイクは成功しないので 3DCG ツール側で行ったほうがよさそう。

 

今回はここまで。

iOS で SceneKit を試す(Swift 3) その32 - コードからカスタムジオメトリをつくってみる

コードからジオメトリをつくろうと思う。
ほぼ、自前でジオメトリを描画することはないと思われるので今回はさわりだけ。

 

テンプレートにあった宇宙船やビルトインのジオメトリ。
これらはオブジェクトファイルの読み込み、Scene Editor からのドラッグ&ドロップ、コードからクラスを呼び出しなどで手軽に行なっているが、
内部的には今回のような設定を元に描画されている。

 

概要

ジオメトリは外観を設定している情報があり、
その情報から SCNMaterial が光の情報やテクスチャと共にジオメトリの描画情報を作成している。

 

ジオメトリは外観を構成するものは以下のもの

  • ポリゴンを構成するために必要な点の情報(Vertex)
  • ポリゴン表示するための面を構成するために必要なインデックス情報
  • ライトを適用する際に必要な法線情報(Normal)
  • テクスチャを適応するために必要なテクスチャ座標情報(UV 座標)

 

流れ

SCNGeometrySource でポリゴンの情報、法線情報、テクスチャ情報を設定し、
SCNGeometryElement ポリゴンの面をどのように生成するか設定。
この2つを SCNGeometry に渡し、SCNNode の geometry で読み込みシーンに配置する。

 

三角形の平面を描画してみる

以下のコードを viewDidLoad() に設定

// シーン設定
let scnView = self.view as! SCNView
scnView.showsStatistics = true
scnView.allowsCameraControl = true
//scnView.debugOptions = .showWireframe // ワイヤーフレーム表示

let scene = SCNScene()
scene.background.contents = UIColor.darkGray
scnView.scene = scene

// カメラ設定
let cameraNode = SCNNode()
cameraNode.camera = SCNCamera()
cameraNode.position = SCNVector3(2.372,1.473,2.399)
cameraNode.eulerAngles = SCNVector3(-Float.pi * 0.125,Float.pi * 0.25,0)
scene.rootNode.addChildNode(cameraNode)

// ライト設定
let lightNode = SCNNode()
let omniLight = SCNLight()
omniLight.type = .omni
lightNode.light = omniLight
lightNode.position = SCNVector3(0,5,5)
scene.rootNode.addChildNode(lightNode)

// SCNGeometry
let verticesArray = [
    SCNVector3(0, 1, 0),
    SCNVector3(-0.866, -0.5, 0),
    SCNVector3(0.866, -0.5, 0)
]

let indicesArray: [Int32] = [
    0, 1, 2
]

let vertices = SCNGeometrySource(vertices: verticesArray, count: verticesArray.count)
let faces = SCNGeometryElement(indices: indicesArray, primitiveType: .triangles)
let geometry = SCNGeometry(sources: [vertices], elements: [faces])

// SCNNode
let node = SCNNode(geometry: geometry)
node.position = SCNVector3Zero
scene.rootNode.addChildNode(node)

 

verticesArray で反時計回りで三角形の頂点を設定し、 indicesArray で verticesArray に対応した点から面を貼る順序を決めている。

SCNGeometrySource で Vertex の設定をし、SCNGeometryElement で三角のポリゴンを貼る順序を設定。 その後、SCNGeometry でこの2つを設定し、SCNNode に渡している。

 

ビルドすると三角が表示される。

f:id:x67x6fx74x6f:20170713182048p:plain

今回、三角形で面を張っているが、点、線、OpenGL などでもあった Triangle Strip などを使用することもできる。

 

ライトを適応してみる

SCNGeometry の部分を変更

// SCNGeometry
let verticesArray = [
    SCNVector3(0, 1, 0),
    SCNVector3(-0.866, -0.5, 0),
    SCNVector3(0.866, -0.5, 0)
]

let indicesArray: [Int32] = [
    0, 1, 2
]

let normalsArray = [
    SCNVector3(0, 0, 1),
    SCNVector3(0, 0, 1),
    SCNVector3(0, 0, 1)
]

let vertices = SCNGeometrySource(vertices: verticesArray, count: verticesArray.count)
let normals = SCNGeometrySource(normals: normalsArray, count: normalsArray.count)
let faces = SCNGeometryElement(indices: indicesArray, primitiveType: .triangles)
let geometry = SCNGeometry(sources: [vertices, normals], elements: [faces])

 

normalsArray に法線情報を詰め込む。Z 方向を向いた平面なので Z 軸に値を入れている。 SCNGeometrySource で法線情報を格納し、SCNGeometry で設定している。

今回のサンプルでは微妙だが、斜め上にあるオムニライトが適応されている。

f:id:x67x6fx74x6f:20170713182115p:plain

 

テクスチャを適応してみる

何らかの画像を読み込んで、以下のコードに変更

一応、今回使用した画像。

f:id:x67x6fx74x6f:20170713182236p:plain

// SCNGeometry
let verticesArray = [
    SCNVector3(0, 1, 0),
    SCNVector3(-0.866, -0.5, 0),
    SCNVector3(0.866, -0.5, 0)
]

let indicesArray: [Int32] = [
    0, 1, 2
]

let normalsArray = [
    SCNVector3(0, 0, 1),
    SCNVector3(0, 0, 1),
    SCNVector3(0, 0, 1)
]

let texcoordsArray: [CGPoint] = [
    CGPoint(x:0.5, y:0),
    CGPoint(x:0, y:1),
    CGPoint(x:1, y:1),
]

let vertices = SCNGeometrySource(vertices: verticesArray, count: verticesArray.count)
let normals = SCNGeometrySource(normals: normalsArray, count: normalsArray.count)
let texcoords = SCNGeometrySource(textureCoordinates: texcoordsArray)
let faces = SCNGeometryElement(indices: indicesArray, primitiveType: .triangles)
let geometry = SCNGeometry(sources: [vertices, normals, texcoords], elements: [faces])

geometry.firstMaterial?.diffuse.contents = UIImage(named: "tex.png")
geometry.firstMaterial?.isDoubleSided = true

 

texcoordsArray でテクスチャの UV 座標を設定し、
SCNGeometrySource に適応させて、
SCNGeometry に適応。

いつも通り、firstMaterial でテクスチャを設定している。
DoubleSided を設定したので、光の当たらない背面は黒くなる。

f:id:x67x6fx74x6f:20170713182222p:plain

 

確認用にアクションを入れても良いかものしれない。

node.runAction(
    SCNAction.repeatForever(
        SCNAction.rotateBy(x: 0, y: CGFloat(Float.pi), z: 0, duration: 2)
    )
)

 

初歩的なものを書いたが、 全ての物体は三角形で表現できるため、これらを繰り返して三角形を描画していくと立体ができあがり、ビルトインやファイルから読み込むオブジェクトのようなものとなる。

 

余談1

今回 SCNGeometrySource には Vertex, 法線, テクスチャを設定している。 この他にも、ボーン、Vertex Color や Subdivision Surfaces 用の Crease の設定や、設定自体を Data で渡すことができる。

 

余談2

ジオメトリはボーンによるスキニングアニメーションや、他のオブジェクトの Vertex を参照して現在の Vertex を移動させるモーフアニメーション、シェーダーからジオメトリの Vertex を操作してアニメーションを行うことができる。

 

今回はここまで。

iOS で SceneKit を試す(Swift 3) その31 - ビルトインジオメトリ SCNShape(パスからの図形)

SCNText はフォントからジオメトリを作成するが、こちらは UIBezierPath で作成するジオメトリ。

設定値は SCNText 同様にイニシャライズや個別でパスと押出し設定を行う。
面取り(chamfer) も SCNText と同様の設定を行うことができる。

Scene Editor で UIBezierPath をつくることができないため、 SCNShape はコードでしか作成することができない。

 

設定値

プロパティ名 機能
path UIBezierPath を指定
extrusionDepth 押出しの奥行きの値
chamferRadius 面取りの半径
chamferProfile 面取りの形状 UIBezierPath を指定
chamferMode 面取りをする面の設定。front は前面のみ、back は後面のみ、both 両面で初期値はこれが設定されている

 

サンプル

幅、高さ 2 の中に治る星型のパスで、
押出し 0.5、表面のみ面取りし 0.1 で表示している

f:id:x67x6fx74x6f:20170713144731p:plain

 

コード

// シーン設定
let scnView = self.view as! SCNView
scnView.showsStatistics = true
scnView.allowsCameraControl = true
scnView.debugOptions = .showWireframe // ワイヤーフレーム表示

let scene = SCNScene()
scene.background.contents = UIColor.white
scnView.scene = scene

// カメラ設定
let cameraNode = SCNNode()
cameraNode.camera = SCNCamera()
cameraNode.position = SCNVector3(2.372,1.473,2.399)
cameraNode.eulerAngles = SCNVector3(-Float.pi * 0.125,Float.pi * 0.25,0)
scene.rootNode.addChildNode(cameraNode)

// ライト設定
let lightNode = SCNNode()
let omniLight = SCNLight()
omniLight.type = .omni
lightNode.light = omniLight
lightNode.position = SCNVector3(0,5,5)
scene.rootNode.addChildNode(lightNode)

// SCNShape
let shape = SCNShape()

let path = UIBezierPath()
path.move(to: CGPoint(x: 0, y: 0))
path.addLine(to: CGPoint(x: 0.2361, y: 0.7265))
path.addLine(to: CGPoint(x: 1.0, y: 0.7265))
path.addLine(to: CGPoint(x: 0.382, y: 1.1756))
path.addLine(to: CGPoint(x: 0.618, y: 1.9021))
path.addLine(to: CGPoint(x: 0.0, y: 1.4531))
path.addLine(to: CGPoint(x: -0.618, y: 1.9021))
path.addLine(to: CGPoint(x: -0.382, y: 1.1756))
path.addLine(to: CGPoint(x: -1.0, y: 0.7265))
path.addLine(to: CGPoint(x: -0.2361, y: 0.7265))

shape.path = path
shape.extrusionDepth = 0.5

shape.chamferRadius = 0.1
shape.chamferMode = .front

let node = SCNNode(geometry: shape)
node.position = SCNVector3Zero
scene.rootNode.addChildNode(node)

 

今回はここまで。

iOS で SceneKit を試す(Swift 3) その30 - ビルトインジオメトリ SCNText(テキスト)

フォントから作成する 3D テキストのジオメトリ。

NSString もしくは NSAttributedString で使用したいテキストを設定する。

ベースラインではなく、ディセンダ(下の空き)を含めるため、
原点においても文字は左下は原点にこないので注意。

また、文字の奥行きが 0 の場合はポリゴンが両面描画される。

f:id:x67x6fx74x6f:20170713121534p:plain

 

Scene Editor でのパラメーター

オブジェクトライブラリの 3D Text を Scene Editor にドラッグ&ドロップして、Attributes Inspector を開く(Command + Option + 4)

1番上の Text の項目で設定値が変更できる

f:id:x67x6fx74x6f:20170713121606p:plain

 

Text

表示する文字列。

 

Font

フォントとフォントの大きさの設定。

初期値は Helvetica のレギュラーで、サイズは 36 ポイント。

 

Extrusion depth

3D テキストの奥行き
初期値は 1。

 

Flatness

3D テキストのカーブなど湾曲している部分のポリゴンの細かさ。
初期値は 0.6。

0 で最も細かくなる。

 

Chamfer radius

3D テキスト角部分の面取りの大きさ。
初期値は 0 で面取りは行われない。

 

Chamfer profile

パスから面取りの形を設定する。

Scene Editor からはエッジに丸みが帯びる Round と直線の Straight のみ選択できる

 

Scene Editor 以外で設定できる項目

プロパティ名 機能
string 表示する文字列を設定する。NSAttributedString での設定も可能
font UIFont 設定する
containerFrame CGRect で SCNText の大きさを設定できる
isWrapped 文字の折り返し設定
truncationMode トランケート設定
alignmentMode 文字の向き(右寄せ、中央、左寄せ、など)
textSize 文字の大きさ設定。ドキュメントにはこのプロパティが書いてあるが SCNText の定義で見つけることができなかったため使用できるか不明。

 

例: containerFrame による表示領域指定

f:id:x67x6fx74x6f:20170713121942p:plain

 

例: truncationMode によるトランケート指定

領域内に文字が入らないため、「…」でトランケート表示される

f:id:x67x6fx74x6f:20170713122031p:plain

 

注意点

  • containerFrame で表示サイズを設定しない場合は isWrapped、truncationMode、alignmentMode は使用できない。

  • NSAttributedString が設定されると font、isWrapped、truncationMode、alignmentMode 設定していても無視される。 なので、自前でアトリビュートを設定する。

  • chamferProfile は始点が (x: 0.0, y: 1.0)、終点 (x: 1.0, y: 0.0) の間で設定されている UIBezierPath を与えると描画される

  • chamferRadius、chamferProfile などが正しく設定されていない状態で flatness を 0 にするとクラッシュすることがある。

  • SCNText のマテリアルは [前面文字、前面 chamfer、伸びている部分、後面 chamfer、後面文字] の5つの配列で構成される。
    指定されない場合は、通常どうり firstMaterial が適応される。

 

例: chamferProfile と マテリアル指定

f:id:x67x6fx74x6f:20170713123209p:plain

 

コード

// シーン設定
let scnView = self.view as! SCNView
scnView.showsStatistics = true
scnView.allowsCameraControl = true

let scene = SCNScene()
scene.background.contents = UIColor.white
scnView.scene = scene

// カメラ設定
let cameraNode = SCNNode()
cameraNode.camera = SCNCamera()
cameraNode.position = SCNVector3(2.372,1.473,2.399)
cameraNode.eulerAngles = SCNVector3(-Float.pi * 0.125,Float.pi * 0.25,0)
scene.rootNode.addChildNode(cameraNode)

// ライト設定
let lightNode = SCNNode()
let omniLight = SCNLight()
omniLight.type = .omni
lightNode.light = omniLight
lightNode.position = SCNVector3(0,5,5)
scene.rootNode.addChildNode(lightNode)

// SCNText
let text = SCNText(string: "SCNText!!!", extrusionDepth: 1)

//text.containerFrame = CGRect(x: -0.5, y: -2, width: 2, height: 4)
//text.isWrapped = false
//text.truncationMode = kCATruncationEnd
//text.alignmentMode = kCAAlignmentCenter
//text.font = UIFont(name: "Futura-Bold", size: 0.5)

// NSAttributedString 設定
let style = NSMutableParagraphStyle()
style.lineSpacing = -0.5

let textFont:UIFont = UIFont(name: "Futura-Bold", size: 0.5)!

text.string = NSAttributedString(string: "SCNText!!!", attributes: [
    NSParagraphStyleAttributeName: style,
    NSFontAttributeName: textFont
])

// その他の設定
text.flatness = 0.0
text.extrusionDepth = 1
text.chamferRadius = 0.02

// chamfer の形状設定
let path = UIBezierPath()
path.move(to: CGPoint(x: 0.0, y: 1.0))
path.addLine(to: CGPoint(x: 0.0, y: 0.75))
path.addLine(to: CGPoint(x: 0.25, y: 0.75))
path.addLine(to: CGPoint(x: 0.25, y: 0.5))
path.addLine(to: CGPoint(x: 0.5, y: 0.5))
path.addLine(to: CGPoint(x: 0.5, y: 0.25))
path.addLine(to: CGPoint(x: 0.75, y: 0.25))
path.addLine(to: CGPoint(x: 0.75, y: 0.0))
path.addLine(to: CGPoint(x: 1.0, y: 0.0))

text.chamferProfile = path

// マテリアル設定

let m1 = SCNMaterial()
let m2 = SCNMaterial()
let m3 = SCNMaterial()

m1.diffuse.contents = UIColor(red: 0.7, green: 0.7, blue: 0.7, alpha: 1.0)
m2.diffuse.contents = UIColor.red
m3.diffuse.contents = UIColor.yellow

text.materials = [m3,m2,m1,m2,m3]


let node = SCNNode(geometry: text)
node.position = SCNVector3Zero
scene.rootNode.addChildNode(node)

 

今回はここまで。

iOS で SceneKit を試す(Swift 3) その29 - ビルトインジオメトリ SCNTube(チューブ型)

チューブ型のジオメトリ。

f:id:x67x6fx74x6f:20170712161450p:plain  

Scene Editor でのパラメーター

オブジェクトライブラリの Tube を Scene Editor にドラッグ&ドロップして、Attributes Inspector を開く(Command + Option + 4)

1番上の Tube の項目で設定値が変更できる

f:id:x67x6fx74x6f:20170712161504p:plain

 

Dimensions

Inner radius

チューブ内側の円の半径。
初期値は 0.5。

Outer radius と同じするとチューブの厚さがなくなる。  

Outer radius

外周の半径。
初期値は 1。

Inner radius と同じするとチューブの厚さがなくなる。

 

Height

ジオメトリの高さ
初期値は 1。

 

Segment Count

Radial

外周の分割数。
初期値は 48。

 

Height

高さの分割率。
初期値は 1。

 

外周を 16、高さを 4 の分割数に設定したもの。

f:id:x67x6fx74x6f:20170712161513p:plain

 

コード

// シーン設定
let scnView = self.view as! SCNView
scnView.showsStatistics = true
scnView.allowsCameraControl = true
scnView.debugOptions = .showWireframe // ワイヤーフレーム表示

let scene = SCNScene()
scene.background.contents = UIColor.white
scnView.scene = scene

// カメラ設定
let cameraNode = SCNNode()
cameraNode.camera = SCNCamera()
cameraNode.position = SCNVector3(2.372,1.473,2.399)
cameraNode.eulerAngles = SCNVector3(-Float.pi * 0.125,Float.pi * 0.25,0)
scene.rootNode.addChildNode(cameraNode)

// ライト設定
let lightNode = SCNNode()
let omniLight = SCNLight()
omniLight.type = .omni
lightNode.light = omniLight
lightNode.position = SCNVector3(0,5,0)
scene.rootNode.addChildNode(lightNode)

// SCNTube
let tube = SCNTube(innerRadius: 0.5, outerRadius: 1, height: 1)

/*
tube.innerRadius = 0.5
tube.outerRadius = 1
tube.height = 1
*/

tube.radialSegmentCount = 16
tube.heightSegmentCount = 4


tube.firstMaterial?.diffuse.contents = UIColor.black // ワイヤーフレームを見やすくするため黒色に。

let node = SCNNode(geometry: tube)
scene.rootNode.addChildNode(node)

 

今回はここまで。

iOS で SceneKit を試す(Swift 3) その28 - ビルトインジオメトリ SCNTorus(ドーナツ型)

ドーナツ型のジオメトリ。

f:id:x67x6fx74x6f:20170712155744p:plain

 

Scene Editor でのパラメーター

オブジェクトライブラリの Torus を Scene Editor にドラッグ&ドロップして、Attributes Inspector を開く(Command + Option + 4)

1番上の Torus の項目で設定値が変更できる

f:id:x67x6fx74x6f:20170712155804p:plain

 

Dimensions

Ring Radius

オブジェクト全体の半径。
初期値は 1。

球と同様に半径であるため倍の大きさになる。  

Pipe Radius

ドーナツのパイプ状になっている部分の半径。
初期値は 0.25。

値を大きくするとリング部分が大きくなり、穴は小さくなる。

 

Segment Count

Scene Editor では初期値が 0 になっている。

 

Ring

外周の分割数。
初期値は 48。

 

Pipe

ドーナツのパイプ状になっている部分の分割数。
初期値は 24。

 

外周を 16、パイブ部分を 8 の分割数を設定したもの。

f:id:x67x6fx74x6f:20170712155839p:plain

 

コード

// シーン設定
let scnView = self.view as! SCNView
scnView.showsStatistics = true
scnView.allowsCameraControl = true
scnView.debugOptions = .showWireframe // ワイヤーフレーム表示

let scene = SCNScene()
scene.background.contents = UIColor.white
scnView.scene = scene

// カメラ設定
let cameraNode = SCNNode()
cameraNode.camera = SCNCamera()
cameraNode.position = SCNVector3(2.372,1.473,2.399)
cameraNode.eulerAngles = SCNVector3(-Float.pi * 0.125,Float.pi * 0.25,0)
scene.rootNode.addChildNode(cameraNode)

// ライト設定
let lightNode = SCNNode()
let omniLight = SCNLight()
omniLight.type = .omni
lightNode.light = omniLight
lightNode.position = SCNVector3(0,5,0)
scene.rootNode.addChildNode(lightNode)

// SCNTorus
let torus = SCNTorus(ringRadius: 1, pipeRadius: 0.25)

/*
torus.ringRadius = 1
torus.pipeRadius = 0.25
*/

torus.ringSegmentCount = 16
torus.pipeSegmentCount = 8

torus.firstMaterial?.diffuse.contents = UIColor.black // ワイヤーフレームを見やすくするため黒色に。

let node = SCNNode(geometry: torus)
scene.rootNode.addChildNode(node)

 

今回はここまで。