8
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

SceneKitAdvent Calendar 2018

Day 15

SceneKitでベジェ曲線から3Dモデルを作ろう

Last updated at Posted at 2018-12-02

3DモデルをXcodeで作る方法は、

  • プリミティブなジオメトリを組み合わせて作る方法
  • カスタムジオメトリを作る方法

の大きく分けて2つだと思います。

昨日は、SceneKitでプリミティブなジオメトリから3Dモデルを作ろうという記事で、前者の方法を紹介しました。

今回は後者のカスタムジオメトリを作る方法の中でも、BezierPathを使って行う方法を紹介したいと思います。

目標

こんな感じのシンプルなダイヤモンドを作ってみましょう。

IMG_299955A9F155-1.jpeg

コードでSCNNodeを作成するときの基本

まず、コードでSCNNodeを作成するときの基本は以下ような形です。

  1. ジオメトリ作成
  2. マテリアルを当てる
  3. SCNNode作成
// ジオメトリ作成
let geometry = SCNBox(width: 0.5, height: 0.5, length: 0.01, chamferRadius: 0)

// マテリアルを当てる
geometry.firstMaterial?.diffuse.contents = UIColor.yellow

// Nodeに渡してNodeをイニシャライズ
let node = SCNNode(geometry: geometry)

BezierPathでジオメトリを作る

SCNShapeというSCNGeometryを継承した型があって、以下のようにinitすることができます。

convenience init(path: UIBezierPath?, 
  extrusionDepth: CGFloat)

つまり流れとしては

// path作成
let path = UIBezierPath()

// pathを渡してジオメトリ作成
let geometry = SCNShape(path: path, extrusionDepth: 0.2)

// マテリアルを当てる
geometry.firstMaterial?.diffuse.contents = UIColor.yellow

// Nodeに渡してNodeをイニシャライズ
let node = SCNNode(geometry: geometry)

という感じです。

ダイヤモンドのBezierPathを作成する

ベジェ曲線とは

まずは、ベジェ曲線とは何か確認しときましょう。

コンピューターで図形の曲線を描くために使われている数式。曲線を始点、終点とそれぞれの方向点の4つの点の座標をもとに描画する。自由度が高く、ほとんどすべての曲線を表現できる。アドビ システムズ社のIllustratorやコーレル社のCorelDRAWなどのドロー系ソフトで曲線の表現方法として採用されているほか、PostScriptのフォントの記述方法にも採用されている。
https://kotobank.jp/word/%E3%83%99%E3%82%B8%E3%82%A7%E6%9B%B2%E7%B7%9A-8655

ベジェ曲線を使うと、点と点から曲線を描くことができます。

iOS、Swiftでもこれを使うことができます。

Swiftでベジェ曲線

以下のように4点を結んで、ダイヤモンドを作ります。

  1. 始点にmoveする
  2. addLineして線を繋いでいく
  3. closeして線を閉じる
IMG_67426123B7B4-1.jpeg

これをコードで示すと以下のようになります。

let path = UIBezierPath()
path.move(to: CGPoint(x: 1, y: 0))
path.addLine(to: CGPoint(x: 0, y: -1))
path.addLine(to: CGPoint(x: -1, y: 0))
path.addLine(to: CGPoint(x: 0, y: 1))
path.close()

作ったUIBezierPathをSCNShapeに渡す

ダイヤモンドのUIBezierPathができたのでこれをSCNShapeに渡して立体的にしていきましょう。

// path作成
let path = UIBezierPath()
path.move(to: CGPoint(x: 1, y: 0))
path.addLine(to: CGPoint(x: 0, y: -1))
path.addLine(to: CGPoint(x: -1, y: 0))
path.addLine(to: CGPoint(x: 0, y: 1))
path.close()

// pathを渡してジオメトリ作成
let geometry = SCNShape(path: path, extrusionDepth: 0.2)

// マテリアルを当てる
geometry.firstMaterial?.diffuse.contents = UIColor.yellow

// Nodeに渡してNodeをイニシャライズ
let node = SCNNode(geometry: geometry)

extrusionDepthは厚さです。上記コードでは0.2(m)の厚さです。

アウトプット

デバッグして、SceneKitやARKitで空間に置くと以下のようになるはずです。

IMG_299955A9F155-1.jpeg

応用

UIBezierPathで作れる形は何でも立体にできます。

例えば、iOS で星型の図形を UIBezierPath で作る
を参考に星型のUIBezierPathを作ることができれば、星の立体を作成することもできます。

star.gif

僕のARKitのサンプルコード集の中でもやってみましたので気になる方は参考にしてください。
https://github.com/kboy-silvergym/ARKit-Emperor

まとめ

  • geometryをNodeに渡すのがコードで3Dモデルを作る基本
  • UIBezierPathはmoveしてaddLineしてcloseして作る
  • SCNShapeというgeometryはUIBezierPathを渡して好きな形状を作れる
8
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?