Apple Engine

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

ARKit や SceneKit で使用している simd について - 型の初期化と演算子編 -

前回に引き続き simd の説明で、今回は simd 型の初期化と演算子に付いて。
行列型に関して他の記事で紹介する。

今回は ARKit や SceneKit で主に使用する以下のものの説明。
double は float と上限値以外は同じなので割愛。

  • float3
  • float4

 

直接使用することはないが simd_bool という Bool 型の Type Alias がある。

 

また、今回使用しない以下のものに関しても使い方は float とさほど変わりはない。

  • simd_short
  • simd_ushort
  • simd_int
  • simd_uint
  • simd_long
  • simd_ulong

 

float3 (simd_float3)

3つの Float 型を持つ型(構造体)
C / Objective-C の vector_float3 と C++ の simd::float3 と同等のもの。
simd_float3 は float3 の Type Alias。

 

初期化

パラメーターが3つあるため x, y, z で Float 値の読み書きが可能。
float3()、float3.init() で初期化した際には x, y, z には 0 が入り、パラメーターが1つの場合は同じ値が3つはいる。

配列での代入も可能で、数字での添字でも読み書きが可能。

var f3:float3
f3 = float3()                       // float3(0.0, 0.0, 0.0)
f3 = float3(1.0)                    // float3(1.0, 1.0, 1.0)
f3 = float3(1.0, 2.0, 3.0)          // float3(1.0, 2.0, 3.0)
f3 = float3(x: 1.0, y: 2.0, z: 3.0) // 上と同じ
f3 = float3([1.0, 2.0, 3.0])        // 上と同じ

f3.x // 1.0
f3.y // 2.0
f3.z // 3.0

f3[0] // f3.x と同じ
f3[1] // f3.y と同じ
f3[2] // f3.z と同じ

 

演算子

== や != での論理演算、符号の変更、四則演算が可能。
掛け算と割り算で片方がスカラーのものがあるが、左辺右辺が逆でも演算可能

var f3 = float3()
var f3_000 = float3(0)

f3 == f3_000 // true


var f3_222 = float3(2)
var f3_123 = float3( 1.0, 2.0, 3.0 )

f3_123 + f3_222 // float3( 3.0, 4.0, 5.0 )
f3_123 - f3_222 // float3(-1.0, 0.0, 1.0 )

-f3_222         // float3(-2.0, -2.0, -2.0)

f3_123 * f3_222 // float3( 2.0, 4.0, 6.0 )
f3_123 * 2      // float3( 2.0, 4.0, 6.0 )

f3_123 / f3_222 // float3(0.5, 1.0, 1.5)
f3_123 / 2      // float3(0.5, 1.0, 1.5)

var f3_Plus     = float3(6)
var f3_Minus    = f3_Plus
var f3_Product  = f3_Plus
var f3_Divide   = f3_Plus

f3_Plus    += f3_222 // float3(8.0, 8.0, 8.0)
f3_Minus   -= f3_222 // float3(4.0, 4.0, 4.0)
f3_Product *= f3_222 // float3(12.0, 12.0, 12.0)
f3_Divide  /= f3_222 // float3(3.0, 3.0, 3.0)

 

その他

Collection のプロトコルが適応されているため、map() や for in での列挙ができる。
また、CustomDebugStringConvertible に適合しているため、print などで文字出力がされる。

f3_123.map{ print("Value: \($0)") }
// Value: 1.0
// Value: 2.0
// Value: 3.0

for i in f3_123 {
    print(i)
}
// 1.0
// 2.0
// 3.0

print(f3_123) // float3(1.0, 2.0, 3.0)

 

float4 (simd_float4)

4つの Float 型を持つ型(構造体)
C / Objective-C の vector_float4 と C++ の simd::float4 と同等のもの。
simd_float4 は float4 の Type Alias。

演算子、その他に関しては float3 と同じなので割愛。

 

初期化

パラメーターが4つあるため x, y, z, w で Float 値の読み書きが可能。
float3 同様、初期化した際には x, y, z, w には 0 が入り、パラメーターが1つの場合は同じ値が4つ入る。

var f4:float4
f4 = float4()                               // float3(0.0, 0.0, 0.0, 0.0)
f4 = float4(1.0)                            // float3(1.0, 1.0, 1.0, 1.0)
f4 = float4(4.0, 3.0, 2.0, 1.0)             // float3(1.0, 2.0, 3.0, 1.0)
f4 = float4(x: 4.0, y: 3.0, z: 2.0, w: 1.0) // 上と同じ
f4 = float4([4.0, 3.0, 2.0, 1.0])           // 上と同じ

f4.x // 4.0
f4.y // 3.0
f4.z // 2.0
f4.w // 1.0

f4[0] // f4.x と同じ
f4[1] // f4.y と同じ
f4[2] // f4.z と同じ
f4[3] // f4.w と同じ

 

simd_make 系を使用した初期化

2パターンあり、1つは float2, float3 を使って初期化する。
引数の順番は全てのパターンが定義されているため自由。

// float4(0.0, 1.0, 2.0, 3.0)
let float4_3_1 = simd_make_float4(float3(0,1,2), 3)
let float4_2_2 = simd_make_float4(float2(0,1), float2(2,3))
let float4_2_1_1 = simd_make_float4(float2(0,1), 2, 3)

 

もう1つは引数で余った成分(要素)を 0 で埋める。

サフィックスで undef がつくものと付かないものがあるが、値の入れ忘れた時わかりやすいように 0 で埋める場合は undef の方が良いと思われる。

(Swift Playground で undef 系の返り値がおかしくなる場合があるので注意)

// float4(1.0, 0.0, 0.0, 0.0)
let float4_1 = simd_make_float4(1)

// float4(1.0, 2.0, 0.0, 0.0)
let float4_2 = simd_make_float4(float2(1,2))

// float4(1.0, 2.0, 3.0, 0.0)
let float4_3 = simd_make_float4(float3(1,2,3))

let float4_1u = simd_make_float4_undef(1)
let float4_2u = simd_make_float4_undef(float2(1,2))
let float4_3u = simd_make_float4_undef(float3(1,2,1))

 

SceneKit での使用例:nodeA の座標から nodeB の座標を求める

nodeA の子ノードに nodeB をする際、事前に nodeA からみた nodeB の座標を計算する。
ワールド座標を nodeB から nodeA に引くだけ。

ちなみに simd で用意されている関数でも同じことが可能。

f:id:x67x6fx74x6f:20181227164736p:plain

let nodeA = SCNNode()
let nodeB = SCNNode()

nodeA.simdPosition = float3(2.0, 0.0, 0.0)
nodeB.simdPosition = float3(2.0, 2.0, 0.0)

let calc = nodeB.simdWorldPosition - nodeA.simdWorldPosition
// float3(0.0, 2.0, 0.0)

 

まとめ

float3、float4 も Float の値を入れ初期化し、簡単に計算できることがわかったと思われる。

次回は simd 用意されている関数について。

ARKit や SceneKit で使用している simd について - 概要編 -

ARKit や SceneKit で使用している Accelerate フレームワークの simd ライブラリについて書いてみる。

元々は Accelerate フレームワークで vImage、vDSP や BLAS、LAPACK などを使用する際に、ハードウェアに近い部分での計算を行うために追加されたものだと予想される。

 

iOS 11 の SceneKit から SIMD 命令が使用できるようになっており、
以前の Apple のサンプルではサンプルのソースに simd で計算するためのカスタム関数使っていたが、 直接値を渡すことのできるプロパティが追加された。

ちなみに Apple の公式ドキュメントでは simd 単体と Accelerate のフレームワークとの中に simd のドキュメントがあるので注意。
特に simd 単体の方は説明が「No overview available」になっており、何も書かれていない。

 

ざっくり説明

以前もこのブログで記事にしているが、雑に説明すると複数のデータ(レーン)を1回の処理で実行する並列化の形。

通常は SISD の形をとっており変数単位で計算を行うが、
SIMD は画像のように [X,Y,Z,W] の計算を1度で行う事ができ高速かつ記述が簡単である。

f:id:x67x6fx74x6f:20180515183839p:plain

 

コードではこの様な感じ。SCNVector 系では計算ができずビルドエラーになる。

var f1 = simd_float3(1,1,1)
var f2 = simd_float3(2,2,2)

var calc1 = f2 + f1 // 結果:float3(3.0, 3.0, 3.0)

var sv3_1 = SCNVector3(1,1,1)
var sv3_2 = SCNVector3(2,2,2)

var calc0 = sv3_2 + sv3_1 // SCNVector3 では計算できないためビルドエラー

 

GPU においては SIMT の実装もされており、
雑に説明すると1レーンに X だけの要素を設定し並列化する。
(厳密に言うとこれは SIMT の説明ではないので注意)

近年の SIMD では4つの値を固定するため、状況によっては Z や W などを使用しない場合があり無駄ができるが、[X,X,X,X], [Y,Y,Y,Y], [Z,Z,Z,Z] などの様に格納されていれば演算時に無駄が少なくなる。

 

注意点

simd の処理は SCNVector 系と同様に行列が列ベクトルで設定され処理されるので注意。
数学で使用する行列の表記と、simd でデータを入れるは異なる場合がある。

 

非公式情報

非公式情報だが iOS 11 Beta 時の SceneKit での simd 関連のヘッダーファイルには、 値が3つ以下のものは GPU、4つのものは CPU (多分 NEON) を使用していると書かれていた。
現在ではその記述がないため夢だったかも。

とはいえ、もし GPU 処理が SIMT で 3-way であるのなら、2つや3つのパラメーターの処理は効率的だろうし、状況によっては他のプロセッサを使用しているのかもしれない。

 

今後の Swift での SIMD

現時点では SIMD は simd.h から持ってきているが今後は Swift 内で実装される可能性がある。

github.com

 

simd ヘッダーファイルで定義されている変数とパラメーター

使用できる変数とパラメーターの数を列挙してみた。
× は過去にあったもの。

1 2 3 4 8 16 32 64
simd_char × × × × × × ×
simd_uchar × × × × × × ×
simd_short × × × × × ×
simd_ushort × × × × × ×
simd_int × ×
simd_uint × ×
simd_float × ×
simd_long × × × ×
simd_ulong × × × ×
simd_double ×

 

SceneKit、ARKit でパラメーターとして渡せるのは float3、float4 や float4x4 で 4 つまで。 正の整数のみ Unsigned はマイナスの値が使用できなくなるため使用機会は少ない。

 

simd のプレフィックスがつく変数は、Swift の場合は全て Type Alias あり、構造体である。

最初の文字が大文字のものは Swift のライブラリ Math で定義されており、小文字のものは simd の vector_types で定義されている。
以下で型をまとめており、列挙しているためわかりづらいが、大文字で定義されている変数はパラメーターが1つしかないものである。

Collection、CustomDebugStringConvertible、Equatable、ExpressibleByArrayLiteral のプロトコルに適応しているため、Array や Dictionary、デバグ用の文字出力や同じ型の simd 同士の演算を行うことができる。

 

simd での定義 元の型
simd_uchar1 Int8
simd_short1 Int16
simd_ushort1 UInt16
simd_int1 Int32
simd_int2 int2
simd_int3 int3
simd_int4 int4
simd_uint1 UInt32
simd_uint2 uint2
simd_uint3 uint3
simd_uint4 uint4
simd_float1 Float
simd_float2 float2
simd_float3 float3
simd_float4 float4
simd_long1 Int
simd_ulong1 UInt
simd_double1 Double
simd_double2 double2
simd_double3 double3
simd_double4 double4

 

過去に C/ObjectiveーC や OpenCL 用に vector というプレフィックスがあったが廃止されている。
以下のものは現状使用できるが廃止されるため、今から使うことはないだろう。

  • vector_int2 = simd_int2
  • vector_int3 = simd_int3
  • vector_int4 = simd_int4
  • vector_uint2 = simd_uint2
  • vector_uint3 = simd_uint3
  • vector_uint4 = simd_uint4
  • vector_float2 = simd_float2
  • vector_float3 = simd_float3
  • vector_float4 = simd_float4
  • vector_long1 = simd_long1
  • vector_ulong1 = simd_ulong1
  • vector_double2 = simd_double2
  • vector_double3 = simd_double3
  • vector_double4 = simd_double4

 

また、simd_〜 は、C++ の simd::〜 に対応しており、 simd_float4、vector_float4、simd::float4 は同じものと考えられる。

 

行列

simd の types に定義されているのは以下のもの。 simd_float2x2 は simd_float2 が2つ、simd_float3x2 は simd_float3 が2つ定義された行列の型(構造体)。
上記の型と同様のプロトコルが設定されている。

  • simd_float2x2
  • simd_float3x2
  • simd_float4x2
  • simd_float2x3
  • simd_float3x3
  • simd_float4x3
  • simd_float2x4
  • simd_float3x4
  • simd_float4x4
  • simd_double2x2
  • simd_double3x2
  • simd_double4x2
  • simd_double2x3
  • simd_double3x3
  • simd_double4x3
  • simd_double2x4
  • simd_double3x4
  • simd_double4x4

 

simd のプレフィックスを抜いた float4x4 などが存在するが、全て simd のプレフィックスが付いたものの Type Alias である。

以前にあった matrix や vector のプレフィックスがつくものは simd の Type Alias になっており相互的使用が可能である。

 

types にはクォータニオンを使用する用途で simd_quatf、simd_quatd が定義されているが、この説明は今後行う。

 

SceneKit のデータ型と simd との互換性

SceneKit のデータ型は以下の4つで、SCNQuaternion は中身は SCNVector4。

SCNVector 系と simd との互換性がある。

SceneKit での型 simd での型
SCNVector3 float3
double3
simd_float3
simd_double3
SCNVector4,
SCNQuaternion
float4
double4
simd_float4
simd_double4
SCNMatrix4 float4x4
double4x4
simd_float4x4
simd_double4x4

 

Swift では以下のように書くが、Objective-C の場合は呼び出すメソッドが Swift と異なるので注意。

let s3 = simd_float3()
let v3 = SCNVector3(s3)

let v4 = SCNMatrix4()
let s4 = double4x4(v4)

 

SceneKit で増えたプロパティ

SceneKit 処理で simd のものを増やしたということは、
simd での処理の方が速いという事になるだろうし、実際に早く処理ができる。
以下、使用できるメソッド。(複数パラメーターがあるものは省略)

  • simdTransform
  • simdPosition
  • simdRotation
  • simdEulerAngles
  • simdOrientation
  • simdScale
  • simdPivot
  • simdRotate
  • simdLocalTranslate
  • simdLocalRotate
  • simdLook
  • simdLocalRight
  • simdLocalUp
  • simdLocalFront
  • simdWorldRight
  • simdWorldUp
  • simdWorldFront
  • simdWorldTransform
  • simdWorldPosition
  • simdConvertPosition
  • simdConvertTransform
  • simdConvertVector

 

まとめ

ARKit、SceneKit で使用することで処理が速くなり、端末の負荷が減ると思われるので、積極的に使用するべきだろう。
また、計算を頻繁に行うのなら SCNVector 系よりコードが短くなる場合がある。

次回、simd で使用する演算や演算用の関数を調べていきたいと思う。

ARKit でタップするカメラに追従する仮想オブジェクト

 

ARKit で仮想オブジェクト動かす際、タップ後スワイプして移動を行うことがあるが、
面倒なのでこういう UI / UX もありかなと試してみることにした。
あと過去の記事で書いたものが実現できるか試してみたかったので。

ARKit とは書いているが SceneKit の機能しか使用していないため、SceneKit を使用したゲームなどでも使うことができる。

ちなみに新規性のあるネタではなく、Microsoft HoloLens でのウインドウ移動が元ネタ。

 

今回使用している SIMD について

iOS 11 の SceneKit から SIMD 命令が使用できるようになっていた。
以前もこのブログで記事にしているが、雑に説明すると複数のデータ(レーン)を1回の処理で実行する並列化の形。

通常は SISD の形をとっており変数単位で計算を行うが、
SIMD は画像のように X,Y,Z,W の計算を1度で行う事ができ高速かつ記述が簡単である。

f:id:x67x6fx74x6f:20180515183839p:plain

SIMD - Wikipedia

 

例えば、simd では計算用のオペレータや関数が存在しているため、直接四則演算が可能だが SCNVector3 では計算できないため中身を取り出す必要がある。

f:id:x67x6fx74x6f:20181221153135p:plain
simd_float3 と SCNVector3

 

ARKit や SceneKit で扱う simd はメリットしかないので積極的に使用していった方がよいだろう。

(自分が記事を書く場合 simd を説明するのが面倒なので SCNVector で説明していることもあるが、Apple のサンプルのノードではほぼ simd で処理している)

 

AR のカメラに追従させる仕組みとは?

やっている事はいたって簡単で ARKit のカメラノードで addChildNode を使用して仮想オブジェクトを子にしているだけ。
追従をやめたい場合は他のノードに addChildNode し直す。

仮想オブジェクトをカメラノードの子のノードにする際、気をつける点はカメラノードのローカル座標に設置されるため、座標値と回転をカメラに合わせて変更する必要がある。

今回の処理はカスタムのコンストレイントや SceneRenderer の delegate でも可能だが共に毎フレーム処理が走るため、カメラの子ノードに設定する方が端末には優しいはず。

 

実装してみる

仮想オブジェクトをタップするとカメラに追従し、もう一度タップすると最初にタップした位置に戻る。  

 

シーンファイル

追従する仮想オブジェクトは空のノードの子にする。
カメラノードの子になった際の位置や回転を補正する計算や オブジェクト自体が移動、回転、拡大縮小などのアニメーションが行われている場合の計算を簡単にするため。

f:id:x67x6fx74x6f:20181221153231p:plain
ルートノードのオブジェクトは親に空ノードが追加されている

 

位置を戻す際に使用するグローバル変数

Dictionary にノードの名前をキーとして Transform (simd_float4x4) で保持させる。
そのため、仮想オブジェクトの名前がかぶるとおかしくなるので注意。

 

AR プロジェクトとタップイベントの作成

Xcode で新規プロジェクト開き(Command + Shift + N)、
「Augmented Reality App」を選択して、いつも通り viewDidLoad() でタップイベントを設定する。

override func viewDidLoad() {
    super.viewDidLoad()

    ・
    ・
    ・
    
    // add a tap gesture recognizer
    let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(_:)))
    sceneView.addGestureRecognizer(tapGesture)
}

 

こちらもいつも通り viewDidLoad() の下にタップ時の関数を追加。
タップすると配置した仮想オブジェクトが赤くフェードする。

@objc func handleTap(_ gestureRecognize: UIGestureRecognizer) {
    
    // check what nodes are tapped
    let p = gestureRecognize.location(in: sceneView)
    let hitResults = sceneView.hitTest(p, options: [:])
    
    if hitResults.count > 0 {
        // retrieved the first clicked object
        let result: AnyObject = hitResults[0]
        
        // get its material
        let material = result.node!.geometry!.firstMaterial!
        
        // highlight it
        SCNTransaction.begin()
        SCNTransaction.animationDuration = 0.5
        
        // on completion - unhighlight
        SCNTransaction.completionBlock = {
            SCNTransaction.begin()
            SCNTransaction.animationDuration = 0.5
            
            material.emission.contents = UIColor.black
            
            SCNTransaction.commit()
        }
        
        material.emission.contents = UIColor.red
        
        SCNTransaction.commit()
    }
}

 

位置を保持するための Dictionary を設定する

「@IBOutlet var sceneView: ARSCNView!」の下あたりに以下の命令を追加。
これの内容をチェックして仮想オブジェクトがカメラに追従しているか調べる。

private var nodeDic:Dictionary<String, simd_float4x4> = [:]

 

仮想オブジェクトタップ後にカメラに追従させる

handleTap 関数の「let result: AnyObject = hitResults[0]」の下にまず定数を設定していく。

ARKit の ARSCNView からカメラノードを取得する。

let cameraNode = sceneView.pointOfView!

 

でもって、その下でタップから結果からノードを取得する。
タップされたジオメトリのノードを返すため parent で親のノードを取得し、こちらをカメラの子ノードにする。

let followGeometryNode = result.node! as SCNNode
let followNode = followGeometryNode.parent!

cameraNode.addChildNode(followNode)

 

そのままだと、addChildNodeしただけなので、タップ後カメラノードの原点から followNode が配置され正面を向いて配置されてしまいいきなり移動して不自然。
傾きが 0 であるためカメラに仮想オブジェクトが向いてしまう。

「cameraNode.addChildNode(followNode)」の下に以下を追加。

followNode.simdTransform = cameraNode.simdConvertTransform(followNode.simdTransform, from: nil)

simdConvertTransform でカメラの座標から followNode の座標へ変換し他ので、タップした位置に followNode が調整される。
from が nil になっているのでワールド座標から行なっている。

実機にビルドすると仮想オブジェクトタップするとカメラに追従する。

 

ちなみに convertTransform(simdConvertTransform)で行なっている処理は cameraNode のトランスフォームを逆行列にし回転を変更し followNode のワールド座標での位置を渡すことで同じものとなる。

 

仮想オブジェクトを再度タップすると元の位置へ戻す

先ほど作成したタップ関数の中身

let followGeometryNode = result.node! as SCNNode
・
・
・
followNode.simdTransform = cameraNode.simdConvertTransform(followNode.simdTransform, from: nil)

 

以下のように変更しビルドする。

let followGeometryNode = result.node! as SCNNode
let followNode = followGeometryNode.parent!
let nodeName = followNode.name!
let nodeInfo = nodeDic[nodeName]

if (nodeInfo != nil) {
    sceneView.scene.rootNode.addChildNode(followNode)
    
    followNode.simdWorldTransform = nodeDic[nodeName]!
    
    nodeDic[nodeName] = nil
} else {
    // Save Node Position
    nodeDic[nodeName] = followNode.simdWorldTransform
    
    cameraNode.addChildNode(followNode)
    
    followNode.simdTransform = cameraNode.simdConvertTransform(followNode.simdTransform, from: nil)
}

 

内容的には followNode の名前を取得し nodeName に設定し、
グローバルで設定した nodeDic へ nodeName のキーを中身を読み込む nodeInfo 定数を設定。

nodeInfo がからの場合はまだカメラに追従していない状態であるため、 nodeDic に followNode ワールド座標を保存。

再度、仮想オブジェクトをタップした場合、nodeInfo 中身があるため true 側の処理をする。 処理内容は followNode をルートノードに戻し、followNode に保持した座標を渡して戻し、nodeDic をからにする。

 

追従する場合も、戻す場合も、タップ時のエフェクトが同じでわかりづらいので、
「material.emission.contents = UIColor.red」を以下に変更する。

if(nodeInfo != nil){
    material.emission.contents = UIColor.white
}else{
    material.emission.contents = UIColor.red
}

 

サンプルファイル

記事に書いた機能に加え、スイッチでオフにすると再度仮想オブジェクトタップでタップした位置に留まる処理を追加している。
処理的にはカメラに追従させる際に使った simdConvertTransform で逆のことして戻している。

github.com 

 

まとめ

動作サンプルなので雑に書いているが応用すれば、追従するウインドウや
ものをとって飛ばしたり、物理判定を使用したり、ゲームなどでも使用できると思われる。

iOS 12 Programming の ARKit の章をレビュー(査読)をさせていただきました

f:id:x67x6fx74x6f:20181219122559p:plain

前作の iOS 11 Programming で堤修一さんが執筆担当されている Metal の章のレビューをさせていただきましたが、iOS 12 Programming では ARKit の章のレビューをさせていただいております。

iOS 11 Programming の Metal の章では、あまり貢献できませんでしたが、今回はそこそこお役に立てたのではと思っております。

 

iOS 12 Programming の紹介

iOS 12 Programming では網羅的に新機能が紹介されており、iOS の新機能から Swift、Xcode、Mojave、tvOS の更新まで幅広く紹介されています。

iOS で新規に追加されたフレームワークに関しては今回は追加が少なく、CarPlay、Network、Natural Language、と Web ページ向けの MapKit JS、MusicKit JS 以外は書かれておりお得な一冊だと思われます。

ARKit では新機能が紹介されておりますので iOS 11 Programming を合わせて読んでいただければ、ARKit の全容がほぼほぼ理解できます。

他の章も貴重な内容が多く、多分 tvOS 12 の TVUIKit や UIKit、SpriteKit、SceneKit で先行実装されていたフォーカスのアップデートはこの本以外で語られることはないでしょう。

 

peaks.cc

 

  • 第 I 部 Delightful Experience

    • 第1章 Siri Shortcuts
    • 第2章 Notifications
    • 第3章 Password AutoFill と Authentication Services
  • 第 II 部 Augmented Reality and Machine Learning

    • 第4章 ARKit
    • 第5章 デプス
    • 第6章 Core ML 2, Create ML
  • 第 III 部 Swift, Xcode, Mojave, tvOS

    • 第7章 Swift 4.0 から Swift 4.2 へのアップデート
    • 第8章 Xcode 10 の新機能
    • 第9章 Mojave の新機能
    • 第10章 tvOS 12 の新機能

 

レビューについて

昨今の技術系書籍で行われているプロセスだと思われますが、プライベートの Github のリポジトリに記事やコードが上がり、それに対して Issue を立てるかたちとなっています。

SceneKit や ARKit の API に関しては過去に大体翻訳しており、ある程度覚えているため、文章のレビューに関しては iPhone だけで行なって行なっています。

初期インストールされているノートアプリに書き込んでから Github のサイトのインプットフィールドにペーストする形をとっており、大体作業していた時間は連休3日の中の数時間と平日帰宅後少しだったはず。

iPhone のみで行なっていて困る点は Apple Developer Documentation のリンクを引っ張ってくるのが若干面倒で、iPad を使用していればスプリットできるので楽だったと思います。

また、Github のサイトのインプットフィールドがスマートフォン表示で機能が異なるため、状況によっては Desktop 表示にする必要があります。

 

レビューで得たこと

仕事では主にゲーム関連のデザインや Web のフロントエンドの作業を行なっていることもあり、
日常的に ARKit のアプリをつくってはおらず、曖昧に覚えていた機能が明確になりました。

また、ARKit や iOS SDK に関してはブラックボックスな部分が多く、Metal や SIMD に関しては解説が少ないため、この点をあーでもない、こーでもないと語らうのは面白かったです。

 

まとめ

技術系の本執筆や Blog 記事を書いたり、レビューなど、多分作業時間に対して金銭的に得られるものはあまり多くはないと思われますが、そこで得られるものはわりと大きく、思考の整理と新たな発見、知的好奇心を満たす貴重な機会になると思われます。

 

 

iOS 12 Programming で紹介されていない ARKit 2.0 機能

AREnvironmentProbeAnchor

使用するにしても Automatic で行うと思われるので、あまり知識として必要はないです。

ARKit 2 の環境マッピング AREnvironmentProbeAnchor を試してみる - Apple Engine

ARKit 2 の AREnvironmentProbeAnchor をマニュアル設定で配置する - Apple Engine

 

オブジェクトトラッキング時の参照データのマージとアンカーの複製

API の説明のみ

iOS 12 SDK Bata 3 の ARKit 2 変更内容 - Apple Engine

iOS 12 SDK Bata 4 の ARKit 2 変更内容 - Apple Engine

年末年始に向けて買うべき Apple 製品

2018 年も終わってしまうのでまとめてみる。

 

Apple 製品を買う上でまず知っておくべき知識があり、製品の製造中止後 5 年間でビンテージ製品、7 年でオブソリート製品となり、オブソリートになると Apple では修理ができなくなる。

 

要するに、修理のサポート期間が決まっているため、長く使いたい場合は発売後購入した方が寿命が上がることとなる。

プロ向けに関しては価格が高いが製造中止になるまでの期間が長い。

また、基本的には価格に比例して機能が上がるので、長く使いたい場合は真ん中や上位の構成を選ぶべきだろう。

 

Mac

Mac Pro / iMac Pro / iMac

来年、新しい Mac Pro が出ると宣言しているので Mac Pro は待ち。

もしスペックが欲しいなら Mac Pro より iMac Pro を選択すべし。

Mac Pro 12 core より iMac Pro 8 core の方がスペックが高いので。

 

iMac Pro はエントリーで 8 Core + Xeon 用の命令と GPU が Vega 56、それと 5K ディスプレイ付きだ。

持ち運ばずにラップトップで高スペックにするなら iMac Pro の方がよいだろう。

 

iMac はコスパが良いのだが、2017 より新しいものが出ていないので価格の割には微妙な感はある。

来年出る場合、9世代目の intel CPU と 次の世代の Radeon GPU が載る可能性があるので待つのもよいかも。

 

Mac mini

GPU スペックがあまりいらなく持ち運びをしないなら Mac mini。

スペック的に i3 は微妙だが i5 や i7 はわりと高性能。

CPU で考えると Mac mini i7 は 6 コアの Mac Pro や 2017 の iMac i7 よりスペックが高い。

eGPU を足すと 10 万ぐらい追加投資になるのでストレージやメモリ、高解像度のディスプレイを買うと iMac Pro 8 Core と価格があまり変わらなくなる可能性があるので注意。

 

MacBook / MacBook Air

現状の MacBook に関しては正直買う選択が難しく Air が選択肢かと。

エントリーモデルはマシンスペック的に非力なのでクラムシェルの筐体が必要なく文字ベースの作業なら iPad Pro の方がよい気がする。
当たり前だが i7 版は i5 しかない新しい Air より速い。

 

古い型の MacBook Air を今購入するには厳しいかと。

新しい型の方はディスプレイが狭額縁に伴い 13 インチとなり、USB-C のコネクタが2つ、Touch ID が付き 8 世代の i5 からエントリーモデル 2 コア。

MacBook の i5 より世代が上がっているため、CPU や GPU がスペックが上がっている。

価格、ディスプレイサイズ、Touch ID、マシンスペック、USB-C のコネクタの数から考えると MacBook より Air の方がよいだろう。

 

MacBook Pro

Touch Bar のないものは CPU が型落ちになってしまっているので選択肢から外れる。

以前、このブログで紹介しているように、8世代の CPU になりコア数が上がったので CPU スペックが大幅に上がった。

用途によっては CPU の強化より、メモリやストレージを強化した方がよいかもしれない。

 

15 inch の i9 は i7 の差が少なく、TurboBoost でスペックを高くし動作する場合は一定の条件がある。

GPU の Vega 16, 20 は妥当なアップグレード価格だが、30万の型からしか選択できない。

 

また、eGPU は Thunderbolt 3 の自体の問題でコストに対して劇的スペックが上がらない。

ラップトップを使用したくて、時折 GPU をブーストしたい人向け。

 

iOS 端末と他の製品

iPhone

iPhone X を使用していなく、コスト安く済ませたいなら XR 一択。
8, 8 Plus と値段があまり変わらないので。

7, 7 Plus に関しては Apple A チップ的にスペックが低いのとバッテリー持ちがよくない。

6s、6s Plus、SE は生産終了しているので今から買う端末としては厳しい。

XS と XS Max の場合、どちらかを取るとなると中身が変わらないので、大きさと重さ次第。

Max は大きさ的にポケットに入らないか入りづらく、重さが缶コーヒーぐらいある。

 

iPad

現在販売されている iPad は 3世代目と 10.5 インチ の Pro、9.7 と mini。
長くもたせたいなら3世代目を買うべし。
iPhone のように数年で替えるようなものではないので高いスペックのものを買うのがよいと思う。軽くなったし。

iPad mini に関しては、多分今後ラインナップから外れそうなので、これを買った場合は次回はでかいサイズを買うことになるので厳しさはある。

10.5 インチと 9.7 インチは A10X でまだ戦えるスペックだと思われる。
ただ、アクセサリーは売られなくなる可能性があるのでお早めに。
特に 10.5 インチ。

Pro 11、12.9 インチに関しては Apple Pencil 使うなら 12.9 の方がよいだろう。

狭額縁になり 12.9 が軽くなったとはいえ、Smart Keyboard Folio はそれなりの重さがあるので実際店頭でキーボード込みの重さとサイズを確認してほしい。

 

Apple Watch

通知が頻繁に来る人や運動を計測するなど使用用途が明確な人向けで、商品としては購入が最も難しい。
まわりでつけている人が何人かは脱落した。

試すなら Series 3 でもよいかもしれないが、S チップの高機能化と画面サイズが大きくなっているので 4 でもよいかもしれない。
3 と 4 で差額が少ないし。

サイズとボディ、バンドに関してはお金次第。

多分、1番の障害は充電。
とりあえず3世代目の iPad Pro と USB-C ケーブルを持ち歩けば困った時充電できるよ。

また、Apple Watch の利点としては、Mac に Touch ID がなくても、同じ Apple ID の Apple Watch が近くにあればアンロックできる機能がある。
この機能のためだけに買うには割高だが。

 

Apple TV

iPhone を持っていて、テレビやディスプレイがあるのなら Apple TV を買うべきだろう。4K でも 19,800(税別) で Apple 製品にしては安い方なので。
ただ、来年 A11 か A12 を載せたものが出るかもしれないので次を待つのもあり。

大半の使用用途は AirPlay による iPhone、iPad もしくは Mac の画面転送だろう。

例えば、操作画面や View を大きな画面に転送することができる。

iPhone の場合、複数のアプリを上下や左右にスプリットすることができないため、AirPlay を使用すれば動画をテレビやディスプレイに映し、iPhone では他のアプリを操作することができる。

また動画閲覧を Apple TV のアプリで Amazon Prime、YouTube、Netflix、Hulu、AbemaTV、ニコニコ動画などがあるため、iPhone で操作しながら別画面で動画を再生できる。

Apple TV については音楽を聴いたりコンテンツを閲覧する端末でそれ以上の機能を期待しない事である。

 

AirPods

左右完全なワイアレスイヤフォンで、
今回価格的にも安くおすすめ。
ワイアレス充電が可能な次期バージョンが噂されている。

最強に手軽さがあるイヤフォン。
ケースがある分、Beats の製品の Wチップと比べて稼働時間が長いのが利点。

ただ、東京においては人の量の関係上、Bluetooth が切れたりするし、
自分は周りの音が大きすぎるため、ボリューム上げたり、周囲の音と出力される音の聴き分けに負担がかかるため室内でしか使っていない。

 

現状の Apple 製品の構成例

どの構成でも、映像鑑賞を日常的にして、テレビやディスプレイがあるなら Apple TV を買うことを勧める。

 

据え置き型の Mac + iPad + iPhone

iMac Pro や Mac mini と iPad の構成が最高だとは思っている。
テキストベースの作業やコンテンツの閲覧ならラップトップのiPad で十分かと。
Apple Watch があれば、Mac のアンロックもできる。

 

ラップトップ + iPhone

持ち運び向け。
正直、ラップトップと iPad は微妙に競合するので両方を上手く使い分けするのが難しい。

大きな画面で観たい場合は、ラップトップ、iPhone と共に Apple TV に流すと解決できる。
若干の遅延があるが、純正の Lighting と USB-C の HDMI コネクタとケーブルを買うお金とちょい足すと Apple TV が買えるのでおすすめ。

GPU に関しては eGPU を使用することが前提なら Air や 13 inch などスペックが低いものでもよいかもしれない。

 

iPad + iPhone

Mac で行う作業がなければ iPad で十分だと思われる。

iPad も iOS であり画面の大きさの変化と Apple Pencil の違いと大きなものはないため、iPhone と Apple TV という構成も良いかもしれない。

 

まとめ

一時期と比べて競合しているそこそこ商品があり、少し前と比べて価格が高くなっているので判断が難しくなった。

ひとまず、AirPods や Apple TV を買うだけでも便利さを体験できると思われる。

Geekbench の A12X のスコア

過去記事で雑に予想はしていたが、 Geekbench で A12X のスコアが公開されたのでまとめてみる。

iOS Benchmarks - Geekbench Browser

 

マルチコアで並べてみたが順当にスペックが伸びている。
いつも通り iPad は GPU コアを iPhone より多く積んでいるため Metal 性能が総じて高い。

端末 チップ シングル マルチ Metal
iPad Pro
12.9-inch 3rd
A12X 5004 17915 42458
iPad Pro
11-inch
A12X 5005 17872 42597
iPhone XS A12 4796 11254 21197
iPhone XS Max A12 4797 11201 21750
iPhone XR A12 4795 11205 21250
iPhone 8 Plus A11 4221 10183 15296
iPhone X A11 4213 10144 15237
iPhone 8 A11 4224 10138 15132
iPad Pro
10.5-inch
A10X 3915 9337 29503
iPad Pro
12.9-inch 2nd
A10X 3911 9320 29512
iPad 6th A10 3480 5926 13102
iPhone 7 Plus A10 3440 5792 12781
iPhone 7 A10 3404 5732 12765
iPad Pro
12.9-inch
A9X 3057 5113 15909
iPad Pro
9.7-inch
A9X 2971 4982 15981
iPad 5th A9 2524 4390 10511
iPhone 6s Plus A9 2407 4158 4539
iPhone SE A9 2400 4152 10372
iPhone 6s A9 1383 3904 4200

 

Mac と比較してみる

シングルコアはかなり優っているのでマルチコアを。

A12X は 4 コア以外の 8 世代と 7700K、Xeon などを除き、わりと高い位置にある。

端末 マルチコア
iMac Pro 18 cores 47174
iMac Pro 14 cores 40921
iMac Pro 10 cores 35588
iMac Pro 8 cores 30861
Mac Pro 12 cores 26912
Mac mini i7 6 cores 24042
Mac Pro 8 cores 23303
MacBook Pro 15-inch
i9-8950HK 6 cores
22594
MacBook Pro 15-inch
i7-8850H 6 cores
21401
MacBook Pro 15-inch
i7-8750H 6 cores
21201
Mac mini 2018
i5-8500B 6 cores
20125
iMac 27-inch
i7-7700K 4 cores
19340
iPad Pro
12.9-inch 3rd
17915
iPad Pro
11-inch
17872
iMac 21.5-inch 2017
i7-7700 4 cores
17810
MacBook Pro 13-inch 2018
i7-8559U 4 cores
17639
iPhone XS Max 11201
iPhone XS 11254
iPhone XR 11205
MacBook Pro 15-inch 2013
i7-3635QM 4 cores
11084

 

まとめ

これらの結果を鑑みると A12 および A12X の1コアあたりの性能は intel Core シリーズに匹敵するという感じになってきている。

また、A12X と話題が変わるが、GPU 周りの性能が必要なければ、わりと Mac mini の i5, i7 でも価格の割にはパワフルだなと改めて感じた。

AR UI 概論 抜粋版

f:id:x67x6fx74x6f:20181203164159j:plain

AR の UI について他ではあまり語られていないためまとめてみる。

抜粋したのだが今回は割と長く、最初は UI について書いているため、必要なければ飛ばしていただいて AR の UIAR UI パターンだけでよいと思われる。

また、面倒なのでここでは Mixed Reality についても AR として扱っている。
お許しくださいまし。

 

UI (User Interface ) とは何か

ここで言う、UI とはコンピュータとその利用者の間での情報をやりとりするための入出力インタフェースを指す。
管楽器が口の延長として音が鳴り響くと説明されているように、UI の入力は手などの身体の延長であり、
機械とコミニュケーションをとるための操作。
出力はその操作を促すものや操作を画像や音、アニメーションや動画、アクチュエータによる振動などで反応を返すフィードバックである。

UI とはコンピュータとコミニュケーションを取る手段とその反応であるフィードバックである。
そのため、UI の入出力は我々の身体に大きく依存し、数々の制約がある。

例えば、ボタン。
人の指は握るようにつくられており、本来はボタンを押すようにはつられていない。
指は内側と外側の筋肉に引っ張られるため、ほんの少し握った状態がリラックスした状態だ。
赤ん坊が眠っている際の手の形を思い出してもらえばわかるだろう。 本来なら軽く握った状態で操作する入力装置が世の中に溢れているべきだが、機械的な制約や身体的な制約でそういう装置が少ない。

身体的な制約といえば、人間の腕というものは重い。
腕が痺れた際にもう片方の手で持とうとするとわりと重かったりする。
そのため、壁や空中にボタンがありそれを長時間操作し続けると次第に腕が重くなってくる。
所謂、ゴリラハンド問題であり、Apple はラップトップの画面にタッチスクリーンを利用するテストを幾度と行なったが断念らしい。
液晶のペンタブレットやキーボードなど机の上で操作し手が何かに支えられるためこれが起きづらい。

 

UI の使いやすさ

UI の使いやすさとは使いたい機能へ最短でアクセスできるかどうかである。
それと共にアクセスに生じてしまう待ち時間をどれだけ緩和できるか。

機能が増えてくると UI は複雑になり、ネットワークに繋ぐとなると機能へのアクセスや画面遷移で待ち時間が増える。
どうすれば最短でアクセスできるようになるかを考えたり、 いらない機能を省くなど考えたりするわけだが、問題が多種多様で明確な解はないと思っている。

また、人は慣れだったり学習することで UI 使いやすさが変わってしまう。

 

学習と慣れ

最初は使い方がわからなくても、学習することで UI の使いやすさが変わってくる。

過去の携帯電話ではボタンを押す操作が主流だったが、スマートフォンではタッチパネルでの操作に変更された。
そのため、タップは物理キーの延長でそのまま理解できるが、
ダブルタップやピンチイン/アウトを知らないと拡大縮小ができない。
いまやタッチパネル上での操作は当たり前となっているが、これらは学習して得た技能である。

UI 操作には慣れがあり複雑な操作でも行い続けると速く操作できることがある。
一見、複雑な UI でも操作上の慣れで意味を持ったものになるものもある。(ならないものもあるが……)

慣れには予期せぬエラーを起こす可能性があり、一連の流れで異なるものがある場合、操作ミスをしてしまう場合がある。
使用するアプリによって決定とキャンセルのボタンが異なる場合は間違えて操作する可能性は高くなるだろう。
OS や多くのアプリで UI を統一しているのはこれを軽減するためだ。

また、人は注目の行かないものに対してそれを認識しないことがあるため、 複雑な UI でも部分的にしか見ていない場合もある。

(注目がそれる現象に関しては「見えないゴリラ」という有名な心理実験があるので、その内容の本を参照していただきたい)

それらを考えると複雑さが必ず使いにくいものではないということである。

日本のテレビリモコンはボタンがありすぎて複雑だと話題に上がるが、 わりとリモコンは使用用途に合わせてうまくレイアウトしてある。
(そこにそのボタンってのもあるけど、自分が使用している東芝のリモコンはわりと上手く配置されている気はする)

f:id:x67x6fx74x6f:20181203161103p:plain
TOSHIBA TV リモコン

 

Apple TV などのリモコンはボタンなど操作できる部分が少なく、操作しやすいように思えるが、
テレビで録画した番組を再生するのと、Apple TV でのコンテンツを再生するのでは、
操作するステップは変わらないか、検索しなければいけない分操作が増える可能性もある。

f:id:x67x6fx74x6f:20181203161152p:plain
Apple TV / Fire TV Stick 用のリモコン

 

あと、よく悪い UI で 100 徳ナイフの話題が引き合いに出されるが、
専用の用途につくられたものなので、それ自体に意味があるものである。
100 徳ナイフの意味合いを都合の良い方向に導いており、自分はあまり好ましいとは思えない。

セブンカフェの UI の様にシンプルするだけで使い勝手の向上するとは限らず、使用するユーザーやユーザー層を考慮する必要がある。

 

UI 歴史

長くなるのでかなり飛ばして 2001 年頃から一部。
いつかちゃんと書く。

 

Mac OS X と Windows XP から始まるリッチデザイン(スキューモーフィズム / Skeuomorphism)

一般的にリッチなデザインを使用した UI はカラー表示ができるようになったゲーム端末が発祥だと思われる。
その後、DTM / DAW などクリエイティブ系のもので UI が概念的で伝わりにくいものを現実を模していった。

 

f:id:x67x6fx74x6f:20181203164544j:plain
Propellerheads Reason。裏面を表示させるとシールド(ケーブル)が揺れるなど UI にリアルな表現を追求した。

 

そして、Mac や PC の OS にもその流れがやってくる。

衝撃的な初代 iMac が世に出て数年後、Mac OS X がリリースされ、Aqua という UI が採用され、
メニューバーやウインドウ、アイコンの色調が増え、リッチなアニメーションが行われ、ボタンは飴のような見た目となった。
アイコンはより写実的になり、フォントの表示も美しくなった。

f:id:x67x6fx74x6f:20181203165700p:plain

ジョブズはこの UI で「スクリーン上のボタンはカッコよすぎて舐めたくなるほど」と言っていた程気に入っていたらしい。

この時点で触りたくなる UI というものを何らかのものに模すことで実現しようとしていたように思える。

表示が綺麗になった代償として、描画が重くなりすぎ、UI 表示部分を GPU で補助するようになる。
近年ではスマートフォンも含め当たり前ではあるがこの頃は画期的であった。
(UI の見た目はよくなったが、個人的に OS 的に UI と機能がちゃんとしたと思えたのはかなり先の 10.6 Snow Leopard)

 

もう一つは、同時期のリリースされた OS。
frog design がデザインを行った Windows XP の UI である。

f:id:x67x6fx74x6f:20181203170533p:plain

 

Windows 98、2000 や Me、などは灰色の基調とし青の単色やグラデーションをウインドのタイトルバーという簡素なものだったが、Windows XP ではビビットな色合いとウインドウの枠が光沢が強めのものとなり、立体感が増していった。

その後の Vista ではウインドの一部などが半透明で軽くボカシが入る Windows Aero の Aero グラス が採用され、
すりガラスのような視覚効果持たせることになる。

f:id:x67x6fx74x6f:20181203171019p:plain

 

Windows 8 の際に Windows Aero は消滅したが、
すりガラスの効果は現在の Apple 製品の各 OS では使用されており、近年の Web サイトではたまに見られる表現である。
(確か、Web サイトの CSS の blur を含む filter をリリース版のブラウザで最初にサポートしたのは Apple の Safari だったはず)

そして、Windows 10 で再度採用されることとなった。

 

iPhone の登場、スマートフォンのタッチインターフェイスとミニマムな UI

f:id:x67x6fx74x6f:20181203172854p:plain
iPhone 3G

iPhone 3G からアプリの開発が可能になり、
Android など他のタッチインターフェイスのスマートフォン登場で タッチ操作での Web サイトの閲覧が可能になった。

既存のアプリケーションの操作とは異なり
マウスなどポインティングデバイスを使用せず、指という肉体を使うことで直感的かつ
素早いレスポンスやフィードバックが求められるようになり UI 設計の複雑化が顕著になっていく。

UI や UX などはクリエイティブ系のツールやゲームなどでよく論議されていた議題ではあったが、
この辺りから、ゲームに限らず UI や UX の重要性が各所で語られることとなる。

タッチインターフェイスのスマートフォンの先駆者である iPhone 3G は画面が 3.5 インチ。
当時出ていた携帯電話の中では画面はかなり大きかったが、画面サイズが 320 x 480 と小さく、さらにステータスバーやナビゲーションバー、タブ、ツールバーなど、そこからさらに領域を取られ、iPhone の Human Interface Guidelines 上でボタンには 44px の領域が必要であったため、制限のあるミニマムな UI 設計を強いられることとなった。

その後、iPhone 3GS 発売ししばらくした後 iOS 3.2 とともに、iPhone の OS ベースの iPad がリリースされ、
大画面のタッチインターフェイスの UI とともにタブレットというカテゴリが浸透する。

 

iPhone 3G が端末的に素晴らしいと最初に思ったのは音楽や動画などメディア再生機能やブラウザだったが、もう一点はタッチパネルと UI。
UI として手にして画期的だと思ったのはいくつかあるが、リスト表示をするテーブルビューと表示を階層化するナビゲーションビュー(ナビゲーションバー)だった。

iPod の UI を踏襲したものだが、ナビゲーションで階層化されたテーブルビューを辿れば、基本的にはアプリケーションとして大体の操作ができた点である。テーブルビューの実装的には現状もほぼ表示するセルの部分のみ処理しているため、多量の項目がある状態でスクロールしても端末の負荷がない。

f:id:x67x6fx74x6f:20181203172219p:plain
上にフリックした際には、下から必要なセルが追加され、画面外(上部)に行ったものは消される。基本的には見える部分のセルだけしか描画されない。

(無限スクロールについて:上にスクロールした際は画面で表示する必要のなくなった最上部のセルは破棄され、最下部は表示するためセルを生成する。データが 10000 件あり、セルが同量の 10000 あったとしても、画面に最大 10 個のセルが表示される場合は OS は 10 個までしか表示されず、セルに表示されるデータだけが変わる。iOS 10 では画面外のセルをいくつか描画しておりスクロールの際の引っ掛かりを低減させている)

また、カテゴリ的に分けたい場合は下部のタブを使用すれば、複数の区分をつくることができ、初期からタブの入れ替えができるようになっている。

 

タッチインターフェイスによってより触るためのさらにリッチなデザインが採用され、iPhone のアプリではカレンダーなど革張りのようなヘッダー、メモ帳では紙のような質感など現実に即したスキューモーフィズムと呼ばれるデザイン手法が加速する。

f:id:x67x6fx74x6f:20181203173939p:plain
旧 iOS のメモアプリ
 

その一方で、Ableton の Live という DAW アプリでは音楽制作系には珍しくフラットな UI デザインを持つアプリが現れ始める。
(実は Ableton Live かなり昔からあるアプリで使用用途も今とは若干違った)

f:id:x67x6fx74x6f:20181203152656p:plain
Ableton Live

 

フラットデザイン

iOS 7 からのフラットデザインや tvOS、Android 5.0 Lollipop から始まるマテリアルデザインがその代表的だが、
Windows Phone や Windows 8 から採用された Metro UI のちの Modern UI が先行しており、その知名度を上げるものとなる。

f:id:x67x6fx74x6f:20190213142233p:plain
Windows8

f:id:x67x6fx74x6f:20111227191143j:plain
Windows Phone

Modern UI には更に元があり、 Zune という iPod に対抗するためにつくられたミュージックプレイヤー端末の UI と
iTunes の様な Zune を同期するための Zune Software というものがあった。
個人的に Zune Software の UI は今も好きだ。

f:id:x67x6fx74x6f:20181203152501j:plain
Zune

f:id:x67x6fx74x6f:20181203152538p:plain
Zune Software

 

Zune の UI は Modern UI に酷似ており、Metro UI (Modern UI) は地下鉄のサインのように明瞭にという話だがこれは説明用の後付けらしい。

2012年に聴講した Windows Developer Days で
Microsoft が目指した UI は Crisp(カリッとしたなグラフィック)と言っていたのが印象的だった。
アプリにおいてコンテンツが中心であり Chrome(装飾)を排除するという構想の元、基本的にはコンテンツの境界に罫線を入れずにタイポグラフィだけで表現している。

Windows プラットフォームは Modern UI を採用することで、視認性を高めるとともに、端末の描画負荷を減らす工夫が行われた。

フラットデザインの説明であまりされないのだが、端末の描画負荷を下げることもこのデザインを採用する利点である。

 

フラットデザインの視認性

フラットデザインで視認性について書かれることはあるが、なぜ視認性が高くなるのか書かれているものを見たことがない。
個人的な意見で学術的なものではないが、色や階調を単色にすることで眼はその物体を光っている様に認識するためだと思われる。

写真など強い光が発光する場合は単色で周囲が潰れるし、3DCG などで物体の表面が発光している場合も光が強い場合は単色に近くため、単色というのは光に近いものなのだろう。

f:id:x67x6fx74x6f:20181203175406p:plain
Physically Based Rendering で右側の方に Emission のパラメータを入れ発光している様に設定。ほぼ単色となっており認識がしやすい。

 

人の目が光に対して注目する点を考えると、単色にすることは理にかなっている。
また、自然界において単色のみで彩られたものほとんどないため、 目が向くのもおかしくないだろう。

一応、人の目や脳は光の強さや、どのようなものの光沢なのかなど、色以外にも光の質を判別できる。

 

AR の UI

本題。

一応、AR を軽く説明すると Augmented Reality / 拡張現実 の略称で、 知覚する現実環境をコンピュータにより拡張する技術や拡張された現実環境そのものを指す言葉。
要するに AR とは現実を書き換えることである。

AR のコンテンツはスマートフォン・タブレット(以降スマートデバイス)型とグラス型に分かれ、共通する UI はあるが、ほぼ別物と考えた方がよいだろう。

 

AR と VR の UI の違い

AR は現実空間と合成するため空間上の制限があるが、
VR の場合、360 度の完全な仮想空間でコンテンツを体験をするため仮想空間上の制限がない。

例えば、VR は仮想的に表示している日本の風景からアメリカの風景へ空間移動を行うことができるが、
AR では長距離の空間移動は難しく、現実空間と密接になっており物理に縛られる点には注意して欲しい。
そのため、VR での操作や UI で手軽に行えるものが AR でそのまま流用できない可能性もある。

 

スマートデバイス型の AR と メガネ型の AR

スマートフォン・タブレット(スマートデバイス)とメガネ型の AR で UI というよりもインプットデバイスが異なる。

スマートデバイスは画面をタッチすることとなるが、メガネ型の場合は画面を触ることができない。

メガネ型に関しては、先行してプロダクトが出ている Google Glass や Microsoft HoloLens などがわかりやすいだろう。

f:id:x67x6fx74x6f:20181203182824j:plain
Google Glass

f:id:x67x6fx74x6f:20181203182845j:plain
Microsoft HoloLens

 

Google Glass はツルの部分にタッチセンサがありタッチかスワイプをさせ、 Microsoft HoloLens の場合は視点がカーソルとなり、エアタップと呼ばれるジェスチャで仮想空間のオブジェクトを掴んだり、動かすことで移動させたりしてコントロールを行う。 また、互いに音声でのコントロールを行うことができる。

Microsoft HoloLens ではクリッカーと呼ばれる手持ちのコントローラーがあり、タップをクリッカーのボタンで行うことができる。

f:id:x67x6fx74x6f:20181203183229j:plain
クリッカー

 

AR と広告

Google Glass では広告を表示する事を許可しなかった。頻繁に現れると視覚的に邪魔になったり、視線が移るため事故を起こす可能性が高い。

多分、Apple も仮想空間での広告表示を許さないだろうし、
広告の表示を消すため、数メートル先のバツボタンを押して視界から無くしていく作業が何回続いたら、もう AR を使うことはなくなるだろう。

 

AR とジェスチャーとコントローラー

Microsoft HoloLens では空間を認識する震度センサーとは別に眉間の部分に深度センサーが付いており手の動きによるジェスチャーを認識する。
使用できるのはタップ動作の指を曲げるエアタップとメニューを開く指を上方向につぼめてから開くブルームという動作。

f:id:x67x6fx74x6f:20181203183259j:plain
エアタップ

f:id:x67x6fx74x6f:20181203183319g:plain
ブルーム

 

画面を触る事ができないため、このようなジェスチャーが用意されている。
用意されてはいるのだが、Microsoft 的には他のジェスチャーを推奨していない。
ジェスチャーは国によって意味合いが真逆なるためだと思われる。

スマートデバイスでも、メガネ型でも、手を使用したジェスチャーはわりと面倒で、Microsoft HoloLens でも時折エアタップはミスるし、腕が疲れる。

コントローラーは手を使用したジェスチャーよりは操作がしやすいのだが、物理的に機材をもう1つ持つことになるため、手軽さがなくなるし、充電機器が増える。
スマートデバイスの場合、物理的に持てない場合がある。

 

AR と音声コントロール(音声コマンド)

音声での操作といえば、スタートレックなどの SF やスパイク・ジョーンズ監督の her という映画がわかりやすいだろう。
また、現状のデバイスでも Siri や Google アシスタント、Cortana などのバーチャルアシスタントシステムでコントロールする方が楽な場合もあると思われる。

スマートデバイスの AR では、大抵の場合、画面をタップするため画面にボタンを置く必要がある。
画面自体がコンテンツであるため、操作するためのボタンをたくさん置くことができない。

メガネ型についてはジェスチャーでも書いているが、画面を触ることができない。

そのため、音声でコントロールする事が最短で機能にアクセスできる可能性がある。
すでにスマートスピーカーで音声でコントロールしている場合は便利さがわかると思う。

自分は Microsoft HoloLens でウインドウ操作する際、視線を動かすのが面倒だったので、Adjust、Close など音声でコントロールをしていた。

 

AR と音

現実空間に仮想オブジェクトが配置されるが、仮想オブジェクトの操作などのフィードバックとして SE などの音は有効だと思われる。

VR ではより没入してコンテンツ体験を行なってもらうため、ヘッドフォンなどを使用し外部からの音の情報を遮断する。
AR では現実空間と音をミックスさせるため AirPods など外界の音が拾える様なサウンドデバイスを使用することになるだろう。

また、Microsoft HoloLens は耳の付近にアレイスピーカーが搭載されており、音の距離感なども現実空間とミックスし体験の向上を打ち出している。

 

AR と香り

なぜ香りについて書くかというと、人の記憶で深く記憶するものの1つが匂いだから。
生物が生きぬく上で匂いや香りの嗅ぎ分けが重要であり、 匂いは何かを引き起こすトリガーにできるのではと思っている。

ちなみに、聴覚・視覚・触覚・味覚・嗅覚の順で人はその記憶を忘れていく。

VAQSO Inc. が VAQSO VR という VR コンテンツと連動させるカードリッジ式で匂いを体験させる機材を開発しており、このようなプロダクトが AR でも使用できそうではある。

f:id:x67x6fx74x6f:20181203183651p:plain
VAQSO VR

vaqso.com

 

AR UI パターン

ARKit を参考に他のデバイスや今後予想されうるパターンを考えてみる。

 

2タイプの AR UI

AR アプリでの UI は、画面の前面に表示されるオーバーレイの UI、コンテンツ内 の UI に分かれるとと思われる。
そのため、グラス型の AR コンテンツでのオーバーレイ UI は OS やシステムからのメッセージやアラートになるため、ほぼコンテンツ内 UI となる。

スマートデバイスタイプの場合でも直感的な操作を行うべきなので、 可能な限り表示しているコンテンツ内で操作を行うことができる様にし、
オーバーレイの UI の使用を避ける方向を検討した方がよいだろう。

 

オーバーレイ UI パターン

スマートデバイスでは何らかのオーバーレイの UI が1つ以上必要になるだろう。
基本的にはスマートデバイスの OS の標準 UI である。
そして、そのパターンは以下のものが必要になるのでは予想される。

 

ラベル

画面操作や状態、項目に対して説明や注釈などを使用する際に用いる UI。
ARKit では主にトラッキングの状態やワールドマップのスキャンと読み書き、イメージやオブジェクトトラッキングの状態など、
文字や画像で伝えるべき説明として配置する。
スマートフォンでは画面が iPhone 5 SE など小さいものがあるため、複数を配置するより状態によって内容が書き換わる方が望ましいだろう。

f:id:x67x6fx74x6f:20181203180355p:plain
現実空間で平面認識状態を示すテキストのラベルと状態を再更新させるボタン
 

ボタン

スマートデバイス同様に何かを追加、削除など、行うことに対して決定やキャンセルを行う UI。
個人的には、ゲーム以外で画面上に5個以上ボタンを置く場合は他の UI を検討して見た方が良いと思われる。

 

セレクター

複数ある項目を選択する際に使用する。
日付選択やカラーパレットなども。
タブなどもこちらに含む。

f:id:x67x6fx74x6f:20181203182052p:plain
ピンクで囲っているところに UISegmentedControl があり、周囲の反射画像(環境マップ)の取得をオートにするかマニュアルにするか選択できる

 

スライダー

物の数や大きさなどをボタンをスライドして設定する UI。
コンテンツ内で仮想オブジェクトの状態を変える場合はそのオブジェクトを選択し、ピンチイン・アウトで拡大したりして変更するため、
あまり使用する機会はないかもしれない。
主に、光の加減や、エフェクトなど全体に影響するものを変更する場合に使用する場面で使用することになるだろう。

 

モーダルウインドウ

ウインドウを画面に表示する。
設定など画面に収まらないものを配置し表示するウインドウ。

f:id:x67x6fx74x6f:20181203180754p:plain
+ボタンを押すとポップオーバーが表示され平面に配置するオブジェクトの選択ができる

ここでは ARKit を使用した iOS アプリでのポップアップ/ポップオーバー (UIPopoverController) もその範疇としている。
理由は ARKit の場合、画面が ViewController で覆われると裏にある画面がリセットされてしまうため、 半分覆う様なモーダルウインドウやポップオーバーを使用することがメインになるだろう。

 

アラート / 通知

通常のアラートや通知の UI。
画面が止まってしまうため、危険な状態など注意を引かせたい強い警告などでない限りアラートを使用するケースは少なくラベルで事足りると思われる。
通知に関しては何らかの通知の履歴を残したい場合だろうか。
(iOS の場合アプリ立ち上がっているとその通知は出ないが)

 

コンテンツ内 UI について

オーバレイの UI とは異なり、UI は 現実空間に合成し配置されるため、
配置されるものはできるだけ認識しやすい表示であることが望まれる。
ただし、ゲームでは一見解りづらいアイテムなど認識しづらさに意味を持つものがあるのでその類は除く。

また、現実空間でのジオメトリや UI の設置は距離を伴うので、重要な操作はユーザーが近くで操作できる必要があるだろう。

 

認識しづらい状況や使いづらい状況を回避するには?

現実空間に 3D のジオメトリを UI として合成するため、基本的には現実にある広告や広告看板などを参考にしてもらえば良いと思われる。

とはいえ、現実世界の様に 360度で UI を配置するのはかなり不便だろう。
後ろは目視できないため、スマートデバイスかグラス後ろに向けないと UI 自体が確認できない。
視界に入る場所に設置する様に工夫するべき。

状況によっては、視界に入る場所の UI となると表示領域が狭くなるため、電光掲示板の様な文字が流れる UI も有効だろうと予想される。

視界に入る状況でも、近距離や遠距離に表示される平面状の UI は移動の際に見忘れる可能性がある。
4面や球状のもの、もしくはカメラに表示したい面を必ず向ける様にするとよいだろう。

状況にはよるが 3D の文字も積極的には使わない方が良いと思われる。
インパクトは高いが、真横など見る場所によっては文字が認識ができない。

最も重要なのは仮想オブジェクトで操作するできるものに関しては、必ず操作を促すものを表示すること。
状況によっては背景と同化し仮想オブジェクトと見分けがつかなくなるため。

また、空間上で多量にある類似情報は間引く必要性がある。

f:id:x67x6fx74x6f:20181212184612p:plain
多すぎるアノテーション

 

Google Maps が解りやすく、引いた状態では主要なピンの情報しかないが、ズームするとピンの情報が細かく表示される。

f:id:x67x6fx74x6f:20181211135327p:plain
Google Maps

AR も遠くの情報は省き、近くのものはより詳しい情報を表示した方が良いと思われる。

 

コンテンツ内 UI のインタラクション

Apple の Human User Interface Guidelines の ARKit の箇所でも書かれている様に、仮想オブジェクトに対しては、スマートデバイスのアプリでも使用されている直感的な操作を使うとよいだろう。

仮想オブジェクトをタップでの選択、スワイプでの移動 、ピンチイン/アウトでの拡大縮小など。
Maps のアプリを使用しているとわかると思うが二本指でのスワイプが通常のスワイプになったり、回転がスワイプにミスする事があるのでジェスチャーは注意が必要。

また、ゲームなどのエンタメを除き空間に物理ボタンや操作する UI をできるだけ配置しない方が良いだろう。

自分の様な昔の人間は、テレビに物理的なダイアルやボタンが付いてそれを手で操作していた時代があった。
(物差しとか物理的に長いものとか使ったりも)

その不便さからテレビリモコンというものが生まれたのであり、その過去をまた繰り返す必要はない。

 

コンテンツ内 UI パターン

仮想オブジェクトの設置に関する UI は割愛。

 

ラベル

オーバーレイ UI 同様に文字情報を表示する。
UI は人と機械との会話と書いたように、機械側が機械側がユーザーに投げかけるメッセージである。
グラス型の AR 場合、コンテンツが UI であるため、多用する事になるだろう。

背景と同化するため、わかりやすい表示を心がけるべし。
野外だと外の看板と見分けがつかなくなる可能性があるため。

f:id:x67x6fx74x6f:20181213182611p:plain
わかりやすくするため縁取りをつけてみる

 

ビルボード/電光掲示板

ほぼラベルと同様のもの。
文字数で表示しきれないものや時間で変更する文字を表示する。

一応、映画字幕では1秒に4文字まで決まりがあるので、速い文字のスクロールはされるべきだろうし、
いくつかスクロールする文字があると、目が行きにくくなるので程々に。

 

アノテーション(ピン)

これもラベルに近いもの。
Google Maps 等のピンの様な目印になるオブジェクト。
ラベルやビルボードとは異なり、目的地など完全に固定するものに使用する感じではあるだろう。

 

ガイド

アノテーションなどで目的地を示すことが可能だが、アノテーションの設置場所が遠い場合はその場所への誘導が必要になる。
距離や位置をわかりやすく示す矢印などの UI。

また、空間認識後に平面など現実空間の障害物を示すガイドの表示させる。

f:id:x67x6fx74x6f:20181213192300p:plain
目的地まで矢印を表示する

 

セレクト/セレクター

PC/Mac やスマートデバイス同様に選択状態を表す。
こちらも現実世界と合成するため、周りを回転させるもの、立方体など、球体など、360度で目に付きやすいものを心がける。

f:id:x67x6fx74x6f:20181213171754p:plain
チューブ、立方体、球体での選択領域

 

ハンドル

仮装オブジェトなど操作できる状態を示し、操作可能な UI。

グラス型の場合はオーバーレイの UI に対してタッチなど操作ができないため コンテンツ内に仮装オブジェクトを操作する UI が必要になる。

f:id:x67x6fx74x6f:20181213192545p:plain
キャラクターを動かすためのハンドル

 

フォロアー

AR 空間の中で、重要な仮想オブジェクトがあり、画面上に常に表示しておきたい場合にカメラについていく振る舞いをする。

情報を表示させるためのウインドウやキャラクターなどカメラに追従してくるなど。

 

トラッキング

ARKit の機能である様な現実空間の画像、オブジェクト、顔のトラッキングをして、仮想オブジェクトなどを配置する。

画像をトラッキングして画像に動画を貼り付けたり、トラッキングしたオブジェクトの説明を表示したり。

 

アバター

ARKit 2.0 で追加された空間共有で相手を表すとしてキャラクターを実現させる。

また、操作説明やメニューの補助機能としてのアバター(キャラクター)がコントローラーがわりになっても良いだろう。

 

キーボード/インプット

基本的には OS のものが表示されるだろう。
グラス型の AR の場合スクリーンを触れられないため、コンテンツに UI を表示させるか、音声でコントロールを促すための UI を表示させる必要がある。

 

マップ

ゲームでよくある地図の様なもの。 広範囲に AR の空間を移動する際に迷わなくするためのもの。

 

AR コンテンツでの特殊効果(エフェクト)

UI とは外れるがエフェクトについて。
基本的には仮想オブジェクトを目立たせるために使う。

 

フィルター

現実空間の画像にフィルターをかける事で仮想オブジェクトを注目させることができる。
また、仮想オブジェクトにフィルターをかける事でも。

f:id:x67x6fx74x6f:20181213180813p:plain
通常 / 背景をモノクロ化

 

パーティクル

粒子状のテクスチャやジオメトリを使用し仮想オブジェクトや空間全体を目立たせる。
パーティクル自体のアニメーション動作を伴うためかなり雰囲気が変わる。

f:id:x67x6fx74x6f:20181213181856p:plain
キャラクタの周囲から上方向星のパーティクルが流れることでキャラクタの位置を確認し易くする。

 

ライト

霧に光の筋やスポットライトのボリュームライトなど、空間や仮想オブジェクトの印象を変える演出ができる。

 

カメラエフェクト

光が強く色が飽和するブルーム効果、ピントが合っている部分以外ボケる被写界深度、レンズに反射が映るレンズフレアなど。

f:id:x67x6fx74x6f:20181213173823p:plain
通常カメラ / 露出を上げて Bloom エフェクトを追加したカメラ

 

f:id:x67x6fx74x6f:20181213174634p:plain
カメラからカラーコレクションを適応

 

必要のないものを消す

いずれかの AR 開発環境で実装されているわけではないが、AR は現実を書き換えることができるのであれば逆に消す事も可能だと思われる。(PhotoShop の Content-Aware の様なもの)

例えば、空間共有する際に相手が自分のカメラに映らない様にし、アバターを代わりに設置するなど。

 

仮想オブジェクトの影

仮想オブジェクトの影は可能な限り入れるべし。
影がある場合、仮想オブジェクトがそこにある感じがして、設置位置がわかりやすくなる。
影がない場合は位置以外にもどのぐらいの大きさなのか、宙に浮いているかも認識しづらくなる。

f:id:x67x6fx74x6f:20181213173009p:plain
影あり / 影無し

 

VR へのスイッチ

AR はカメラで背景画像を作成しているため、任意の画像に書き換えてしまうと VR が実現できる。

AR ゲームである場所に行くと完全な仮想空間でボス戦を行うなどに使用できそう。

 

参考書

  • インタフェースデザインの心理学シリーズ
  • デザイニング・インターフェース 第2版
  • ノンデザイナーズ・デザインブック
  • 誰のためのデザイン?

 

インタフェースデザインの心理学に関しては UI に関心がない人でも読むのも良いと思われる。

デザイニング・インターフェースは若干古いが UI パターン網羅されている。

ノンデザイナーズ・デザインブックは文字デザイン向け。デザインや UI の殆どは文字なので勉強という点では良いと思う。
ちなみに古本が安いので旧版でも良いと思われる。

誰のためのデザイン?は良いデザインを考えるための本。こちらも昔のものでも問題はない。

UI に関しては About Face という本も紹介したかったのだが、絶版になってしまった。

 

UI / UX の部分は少ないが、AR の教科書は広範囲に書かれているため、上の本よりまず読む本だろう。

 

AR UI の今後の発展

今回、ARKit 2.0 ベースで考えているため、現実世界の障害物で遮蔽される処理は省いているが、これに関連する有用な UI の出現も考えられる。

カメラ性能の向上や NPU など Neural Engine 用チップを使用し現状のデバイスでは処理できない表現が可能になるかもしれない。

現状では想像可能な UI を羅列したが今後も進化あり、3次元空間での UI の模索をこれからも行う必要がある。