Apple Engine

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

新しい AirPods とワイヤレス充電ケース

f:id:x67x6fx74x6f:20190322173147p:plain

 

新しい AirPods とワイヤレス充電ケースが出ており、リニューアルは約2年ぶり。

AirPods 満充電で最大5時間、15分の充電で最大3時間稼働し 充電ケースを使用した場合、24時間の使用が可能となるのは以前のまま。

1日2〜3時間の使用の場合、1週間はケースを充電しなくても使用でき、今回ワイアレス充電が可能になったため、さらに利便性が向上した。

 

www.apple.com

 

第2世代の変更点

  • W1 から H1 チップに変更
  • AirPods をタップせずに「Hey Siri」の呼びかけで Siri を起動
  • デバイスの切り替えが最大2倍高速化
  • 電話の通話への接続が1.5倍高速化
  • ゲームでのレイテンシが最大30パーセント低減
  • ワイアレス充電ケースが選択可(充電方式は Qi)

 

価格 (税別)

商品名 説明 価格
AirPods
with Wireless Charging Case
AirPods +
ワイアレス充電ケース
¥22,800
AirPods
with Charging Case
AirPods +
Lightning 充電ケース
¥17,800
Wireless Charging Case
for AirPods
ワイアレス充電ケースのみ ¥8,800

 

第1世代は ¥16,800。
今第1世代の新品を購入し、あとでワイアレス充電ケースを買うと
16,800 + 8,800 - 22,800 = 2,800 で ¥2,800 損するので注意。

ワイアレス充電なしの第2世代 AirPods からワイアレス充電ケースを買うと、さらに¥1,000 損するので罠。

ワイアレス充電のケースも Lighting のコネクタは付いているため、無線充電を使用する予定があれば +¥5,000 だけど、¥22,800 払った方がよさげ。

(あとでワイアレスのケースを買うと、既存のケースを予備充電用バッテリーとして使用できるが、モバイルバッテリーが普通に買える)

 

注意点

自分は AirPods を付け歩行等で落ちたことがないが、耳の形状によっては落ちやすいので注意。
使用して落ちやすい様であれば返品して諦めよう。

www.apple.com

 

あと、AirPods 自体持ちやすい形状をしていないため、ケースに収納する際に滑って落としたりするので気をつけるべし。

 

第1世代の AirPods を持っている人は買うべきか?

iPhone など単一デバイスで使用していて、Siri を使用していない場合はいらないだろう。
無線充電ケースだけ買うというのものあり。

第1世代でもセパレートしているタイプのイヤホンとしてはレイテンシが少ない方だが、
ゲームで使用したい場合は買い替えを検討してみてもよいかも。

余談かつ予測だが、
多分、AirPods 端末接続後片方ずつにデータを送っていると予想される。
また、人の頭は水分が多いため装着した場所から頭を通過しても互いの通信するには電波が届かない可能性があり、うどん部分から電波を投げてやっていると思われる。
なので、耳からうどんな形状は致し方なしかなと。

 

AirPods の今後

Bose の聴く AR サングラス Frames の様な現実と情報をミックスする音の AR 機器として真価を発揮すると予想される。
また、出ると噂されている AR グラスがビジュアル的情報を提供するのであれば、音は AirPods を併用することになるだろう。

今後は Apple Watch のバンドや iPhone XR の本体カラーに合わせた AirPods 出るとウェアラブル端末として統一感があってよい気はするし、
H1 チップを使用した新しい Beats 製品も出そうではある。

2019 年版 iMac について調べてみる

f:id:x67x6fx74x6f:20190322160748p:plain

約2年ぶりに iMac が出たので調べてみる。 公式ページによると
21.5 インチ Retina 4K が最大 60% CPU、最大 80% GPU スペックが上がり、
27 インチ Retina 5K が最大 2.4倍 CPU、最大 50% GPU スペックが上がっているとのこと。

今回、コスパの悪い第9世代 i7 は CTO 構成で存在しないところがよいところ。

www.apple.com

 

以下、価格は税別価格。

 

標準構成

標準構成で i7 はなく、メモリーは 8GB となっている。

ディスプレイ CPU CPUコア数 GPU ストレージ 価格
21.5 inch
Retina 4K
第8世代 Core i3 4 555X 1TB HDD ¥142,800
第8世代 Core i5 6 560X 1TB Fusion Drive ¥164,800
27 inch
Retina 5K
第8世代 Core i5 6 570X 1TB Fusion ¥198,800
第8世代 Core i5 (3.1GHz) 6 575X 1TB Fusion ¥220,800
第9世代 Core i5 6 580X 2TB Fusion Drive1 ¥253,800

 

CPU の CTO と価格

ディスプレイ CPU CTO CPU 追加価格 合計価格
21.5 inch
Retina 4K
第8世代 Core i3 Core i7 ¥33,000 ¥175,800
第8世代 Core i5 Core i7 ¥22,000 ¥175,800
27 inch
Retina 5K
第8世代 Core i5 なし
第8世代 Core i5 (3.1GHz) 第9世代 Core i9 ¥55,000 ¥275,800
第9世代 Core i5 Core i9 ¥44,000 ¥297,800

 

GPU の CTO と価格

21.5 inch と 27 inch の高いグレードのみ GPU が変更できる。

21.5 inch は 560X から Vega 20 で
+¥38,500

27 inch は 580X から Vega 48 で
+¥49,500

GPU 性能とアップグレード価格が大体釣り合っているので、お金に余裕があって GPU 性能をあげたい人向けではある。

 

メモリとストレージ の CTO と価格

メモリ

軽いアプリを動作をさせるなら 8 GB でも問題ないが、
Final Cut Pro、Logic Pro X や Adobe 系 などのプロ向けや複数立ち上げたい場合はメモリを 16 GB に設定した方が良さそう。
特に Slack アプリはワークスペースごとに 100 MB 単位でメモリをバカ喰いするので注意。

  • 16GB +¥22,000
  • 32GB +¥66,000
  • 64GB +¥110,000 (27 inch の 2 種類のみ変更可)

 

ストレージ

使い方にもよるが大半の場合、Mac を使用していて一番体感速度が速くなるのがストレージ。

HDD と SSD と比べた場合かなり差があるので HDD のみの構成は選択肢から外した方が良いと思われる。

Fusion Drive は SSD と HDD を合わせて使用するものだが、
以前と同じならば Fusion Drive は 1TB が 32GB SSD、2T, 3T が 128 GB SSD なので、1TB だとシステムだけで SSD が埋まってしまう。
2TB 以上か SSD のもの構成が良さそう。

 

1TB HDD から
ストレージ内容 価格
1TB Fusion Drive +¥11,000
256GB SSD +¥22,000
512GB SSD +¥44,000
1TB SSD +¥88,000

 

1TB Fusion Drive から
ストレージ内容 価格 注釈
2TB Fusion Drive +¥22,000 27 inch のみ選択可能
256GB SSD +¥11,000
512GB SSD +¥33,000
1TB SSD +¥77,000

 

2TB Fusion Drive から
ストレージ内容 価格
3TB Fusion Drive +¥11,000
512GB SSD +¥11,000
1TB SSD +¥55,000
2TB SSD +¥121,000

 

Mac mini と比べてみる

Mac mini は本体価格が安いが、4K / 5K のディスプレイと CPU 一体型ではない GPU が搭載されているため、以前同様に iMac のコストパフォーマンスは高いと思われる。
また、iMac は SDXC カードスロットがある。

ただ、Mac mini の方が USB-C のコネクタが多く、10GB Ethernet を選択できる。
(あと、iMac のスペック表には T2 チップの記載がないため搭載されていない可能性がある)

 

まとめ

iMac はプロ向けという位置付けではなく、Mac 導入向けのもので、ラップトップよりもコスパのよい一体型パソコンであり、
今回は第8世代の Intel Core i5 は第7世代の i7 並みのスペックがあるため標準構成でも結構パワフルになった。

ただ、個人的にメモリを 16 GB、ストレージは 2TB Fusion Drive かコストは跳ね上がるが SSD の構成にした方がよいと思われる。

GPU に関しては Thunderbolt3 によるロスが少ないため、同スペックの eGPU より速くなると予想される。
そのため GPU スペックを上げたい場合は 27 inch の上位機種を選ぶことになるだろう。

 

ちなみに、27 inch で CTO のスペックを iMac Pro 同等にすると ¥468,300 となり、iMac よりスペックが高い iMac Pro と値段が近くなってしまう。

多分 iMac Pro のスペックの優位性は Mac Pro よりもなさそうなので、
中規模価格帯の iMac を 3 〜 5 年のサイクルで回した方が良さそうな感はある。

 

追記

第9世代の Core i9 と iMac Pro の Xeon W 8 コアと比べると i9 の方が世代 UP によるシングルコアのスペックアップで、ベンチマーク上では i9 の方がスペックが高くなってしまった。

 

Xeon 用は専用の機能があるけど、普通はその恩恵を受けることはなさそう。
Vega 48 も 56 と 580X の間と想定していた Metal / OpenCL のベンチという感じ。

とりあえず、変わらず言えるのは第9世代の Core i5 のコスパが良いということ。

iMac Pro (2017) に Vega 64X とメモリ 256 GByte の CTO が追加された

2つの CTO が追加されたので調べてみる。
以下、価格は税別。

 

Radeon Pro Vega 64X

Vega 64X と Vega 64 を仕様の情報から比較すると、
11 から 12 テラフロップスの単精度、
22 から 24 テラフロップスの半精度の向上となり、
約 1.1 倍。

Radeon Pro Vega 64 ¥60,500
Radeon Pro Vega 64X ¥77,000
単純な価格差で考えると 1.27 倍なので割高感はある。

ただ、56 から 64 のジャンプアップが +¥60,500 で 1.22 倍の性能であるため 64 から +¥16,500 で約 1.1 倍 な 64X は魅力的なのではと思われる。

 

メモリ 256 GByte

¥572,000 とかなり高い。 2,666MHz DDR4 ECCメモリ 64GB * 4 を個別で買ってもかなり高いので、
4K、5K 映像の RAM プレビューやメモリを使いまくるアプリを動かす場合検討してみてもよいかも。

まぁ、標準構成の iMac Pro より 256 GByte の方が高いのだが。

 

まとめ

プロ向けツールとして CTO のラインナップを時期で増やすのはよいと思う。

余談だが、新しく出た Pro ではない iMac は高い部類のカスタマイズをしてしまうと数万足すとスペック的に iMac Pro の方がお得になる可能性があるので注意。

2019 年版 iPad Air / iPad mimi の特徴と購入すべき端末

本日、突如新しい iPad Air と iPad mimi が発表されたので調べていく。

iPad Air と iPad mimi は、ほぼほぼ同スペックで、大きさ、重さ、Smart Connector の差ぐらいしか無く、 価格差は ¥9,000 と Apple 製品として考えると少ない。

カラーは第6世代同様にシルバー、スペースグレイ、ゴールド。

10.5 inch がラインナップから消え、iPad Air と iPad mimi で第1世代の Apple Pencil が使用できることとなり、ペンデバイスが指以外 iPad のポインティングデバイスの地位を得たこととなる。

 

ベンチマーク

高い値を赤字にしている。
XR 相当ということなので高い位置を示している。

2世代目の 12.9 inch や 10.5 inch と比べると CPU の伸び率があまり高くなく、GPU のコア数が多い分 Metal のスコアが高い。
そのため、画面サイズを小さくしたい場合以外は早期に乗り換える必要は無いように思われる。

端末 SoC Single Multi Metal
iPad Pro 11 inch A12X Bionic 5006 17901 42590
iPhone XS A12 Bionic 4797 11268 21213
iPhone XR A12 Bionic 4794 11216 21256
iPad 6th A10 Fusion 3484 5935 13161
iPad Pro 12.9 inch 2nd A10X Fusion 3913 9330 29585
iPad Pro 10.5-inch A10X Fusion 3916 9344 29562

 

iPad Air / iPad mimi と iPad Pro との機能差

画面サイズ以外の Pro の利点

  • SoC が 12X Bionic であるため CPU/GPU コア数が多く高性能
  • Pro は第2世代の Apple Pencil であるため、端末のサイドに Pencil をくっつけて充電できるが iPad Air / iPad mimi は端末のライトニングコネクタか付属するアダプタと Lightning ケーブルを使用する必要がある
  • Pro は輝度 600 nit だが、iPad Air / iPad mimi は 500 nit
  • Pro には画面のリフレッシュレートを状況によって数十〜120 FPS に変動することができる ProMotion の機能がある
  • カメラ性能が高く、フラッシュがついている
  • Pro はカメラの出っ張りがあるが、本体の厚さが 0.2 mm 薄い
  • Pro は本体スピーカーが4つある
  • Face ID

 

iPad Air / iPad mimi の利点

  • 3.5mm オーディオジャックがある
  • カメラの出っ張りがない
  • Touch ID

 

iPad Air / iPad mimi と 第6世代 iPad との機能差

iPad Air / iPad mimi の利点

  • SoC が 10 Fusion から 12 Bionic に変更されスペックが 1.4 〜 1.9 倍
  • Neural Engine が追加されている(Face ID がないので使用用途が公式では情報なし)
  • Bluetooth が 5.0
  • 画面がフルラミネーションや反射防止コーティング
  • 広色域ディスプレイ(Display P3)や True Tone ディスプレイ対応
  • フロントカメラが 1.2 メガから 7 メガピクセルに変更
  • 重さ軽く、厚さがかなり薄い
  • セルラー版は eSIM が使える。

 

価格(税別)

iPad Air と iPad mimi の価格差は ¥9,000。
第6世代 iPad とは iPad Air が ¥15,000。
mimi との差は ¥8,000。

個人的にはスペックを考えると第6世代 iPad の選択肢は無い気はする。

端末 容量 回線 価格
iPad Air 64GB Wi-Fi ¥54,800
Cellular ¥69,800
256GB Wi-Fi ¥71,800
Cellular ¥86,800
iPad Mini 64GB Wi-Fi ¥45,800
Cellular ¥60,800
256GB Wi-Fi ¥62,800
Cellular ¥77,800
iPad 32GB Wi-Fi ¥37,800
Cellular ¥52,800
128GB Wi-Fi ¥48,800
Cellular ¥63,800

 

600 nit を有する Lquid Retina Display、
画面の可変フレームレートを実現する Pro Motion、
第2世代の Apple Pencil が必要であれば Pro が購入対象になるだろう。

端末 容量 回線 価格
iPad Pro
11 inch
64GB Wi-Fi ¥89,800
Cellular ¥106,800
256GB Wi-Fi ¥106,800
Cellular ¥123,800
iPad Pro
12.9 inch
64GB Wi-Fi ¥111,800
Cellular ¥128,800
256GB Wi-Fi ¥128,800
Cellular ¥145,800

 

iPad Air / iPad mini は買うべきか

前回の機種や第6世代 iPad と比べると大幅な進化を遂げており、iPad Pro の廉価版としてはちょうどいい機能と価格を実現したと思われる。

第6世代 iPad は 7.5 mm 厚さがあるが、iPad Air / iPad mini は 6.1 mm とかなり薄く、重さに関しても若干 iPad Air の方が軽い。
iPad Air で ¥15,000、mimi で ¥8,000 の差しかないため、 現状で第6世代 iPad の選択肢には入れづらい。
しかも、この価格差ではあるが iPad Air / iPad mini はストレージが倍になっている。

互いに Apple Pencil が使えるようになったが、Ssmart Keyboard は Air の方しか使用できない。
mini はこれまで通り Bluetooth のキーボードを使用する必要がありそう。

また、ロック解除の認証が Touch ID であるため、X、XR、XS、XSMax を使用していると煩わしさを感じるかもしれない。

 

iPad mini

小さい iPad を望んでいた人にとっては、iPad mini はおすすめである。
iPhone XS Max の本体重量が 208g だが、mini はセルラーで 308.2g とかなり軽い。
再度書くが Air とは機能的に差があまりない。

 

iPad Air

9.7 inch と同等の iPad として最良かと思われる。
Pro との差は SoC、ディスプレイ、カメラ、スピーカー、Apple Pencil と全般的に機能アップするので、価格分ジャンプアップすると考えてよい。

また、絵を描くなどペンをメインで使用する作業が多かったり、取り回しを楽にしたかったりするのであれば、+3万弱払って Pro を買った方が満足度は高いだろう。

逆に Smart Keyboard や Bluetooth キーボードをメインでたまにメモ書きする程度なら iPad Air を選ぶとよいだろう。

 

あえて第6世代 iPad を買う必要があるのか

価格が安い以外の利点がないのでそこだけである。

写真や動画の閲覧、ブラウザの閲覧などしか使用しないのであれば、こちらを選択してもよいとは思うが価格差が微妙ではあるし、リリースされて時間が経っている為、本体や OS のサポート期間が少なくなる点は注意してほしい。

個人的はあまりお勧めできない。

 

余談というか妄想

iPad でのポインティングデバイスが Apple Pencil となり、Apple が Mac Pro と共にディスプレイを出すなら、液タブや Surface Pro のように傾けて Apple Pencil を使用できるようになったりするかもしれない。
確率は低いが。

GeekBench に Mac 向けの ARM のベンチマークが掲載されている

/LEAKS に Mac 版 ARM のベンチマークが掲載されているが、高い確率で嘘情報なので信用しない方がよいかも。

GeekBench の検索で該当チップがヒットしないことと、ARM ベースであっても現状で Single Core で 7000 近かったり超えたりするとフルで動かした場合にかなり大きなファンが必要になるため。

 

一応、比較表

Chip Single Multi
謎チップ
10Core 3.4GHz
7335 20580
謎チップ
12Core 3.1GHz
6912 24240
Apple A12X Bionic
2.5 GHz
5006 17901
Intel Xeon W-2150B
3.0 GHz (10 cores)
5321 35876

 

参照元

www.slashleaks.com

ARKit / SceneKit でフォーカスが外れたジオメトリの位置を知らせる UI をつくる

f:id:x67x6fx74x6f:20190315190318p:plain

 

f:id:x67x6fx74x6f:20190315190432g:plain

 

上の画像の様な感じ。

カメラから対象物となるジオメトリがフォーカスから外れるとジオメトリがある方向に、端末を回転する様に促す矢印の UI が出る。
今回はサクッとつくったため、あまり精度はないのでご了承いただきたい。

 

流れ

  • overlayScene に左右矢印を非表示として配置した SpriteKit の SKScene を設定
  • SceneKit のデリゲートでフォーカスが外れた時の処理と対象物の状態を調べる
  • フォーカスが外れていたら左右どちらかの矢印を表示する

 

実装

今回は ARKit のテンプレートを使用する。

まず、ViewController クラスのグローバルに、対象物の SCNNode、overlayScene の SKScene と左右矢印となるスプライトを設定する。

private var target:SCNNode!
private var overlayScene: SKScene!
private var arrowL: SKSpriteNode!
private var arrowR: SKSpriteNode!

 

対象物をシーンファイルかコードで設定。

let scene = SCNScene(named: "main.scn")!

target = scene.rootNode.childNode(withName: "sphere", recursively: true)!

 

SKScene を初期化、左右矢印となるスプライトを設定し alpha を 0 に。
overlayScene に SKScene を設定する。

overlayScene = SKScene()
overlayScene.size = UIScreen.main.bounds.size
overlayScene.anchorPoint = CGPoint(x: 0.5, y: 0.5)

arrowL = SKSpriteNode(imageNamed: "arrow_l.png")
arrowL.anchorPoint = CGPoint(x: 0.0, y: 0.5)
arrowL.position = CGPoint(x: -overlayScene.size.width / 2, y: 0.0)
arrowL.alpha = 0.0
overlayScene.addChild(arrowL)

arrowR = SKSpriteNode(imageNamed: "arrow_r.png")
arrowR.anchorPoint = CGPoint(x: 1.0, y: 0.5)
arrowR.position = CGPoint(x: overlayScene.size.width / 2, y: 0.0)
arrowR.alpha = 0.0
overlayScene.addChild(arrowR)

sceneView.overlaySKScene = overlayScene

 

SceneKit のデリゲートを設定。

func renderer(_ renderer: SCNSceneRenderer, didRenderScene scene: SCNScene, atTime time: TimeInterval) {
    ...
}

 

デリゲートの中で convertTransform を使用してカメラノードから見た対象物をローカル座標を取得するコードを書く。
これで対象物の X 軸でカメラよりマイナスかプラスかわかるので矢印の処理をする。

func renderer(_ renderer: SCNSceneRenderer, didRenderScene scene: SCNScene, atTime time: TimeInterval) {
    let cameraNode:SCNNode! = sceneView.pointOfView
    
    let transform = cameraNode.simdConvertTransform(target.simdTransform, from: nil)

    ...
}

 

そして、その下に矢印の処理を書いていく。

対象物の X 軸のマイナス、プラスのみで処理すると対象物が正面や180度回転方向でも矢印が表示されてしまう。 それを回避するため SCNView のメソッド isNode(target, insideFrustumOf:) でカメラの視体積にある場合は両矢印を表示しないようにする。

if !sceneView.isNode(target, insideFrustumOf: cameraNode) {
    if transform[3][0] > 0 {
        arrowL.alpha = 0
        arrowR.alpha = 1
    }else{
        arrowL.alpha = 1
        arrowR.alpha = 0
    }
}else{
    arrowL.alpha = 0
    arrowR.alpha = 0
}

 

サンプルコードではランドスケープ画面になった時の処理を入れているが、 ひとまずこれをビルドするとコードが動く。

 

サンプル

github.com

ランドスケープ時の左右 Safe Area を考慮し忘れたので適当に直して使って欲しい。

 

まとめ

雑ではあるが簡単に矢印を表示する UI が表示できた。
一応、対象物の Y, Z 軸方向も調べることができるので試してみても良いかも。

ちゃんとしたものを作成したい場合は対象物の大きさ(バウンディングボックス)から範囲を調べ、
画面に対象物が映らない範囲のちょっと内側を調べて設定たり、位置や回転を正しい状態を設定してた方がよいかと思われる。

SceneKit で画像の色情報を元にジオメトリを配置する

f:id:x67x6fx74x6f:20190312154610j:plain
画像の色情報とともにジオメトリを配置

上の画像の様な感じでピクセル分だけジオメトリを複製してマテリアルに色を付ける。

各ジオメトリのマテリアルの色が変わる可能性があり、GPU による Geometry Instancing が働かず、
ドローコールが画像のピクセル分だけ増えるので注意。

iPhone 6s では 2500 ピクセルで 25 FPS 切るため、今回のものが実用的なものではなく実験というものだと思ってほい。
(iPhone XS ではなんとか 60 FPS を出すことができるが……)

原理的には CGImage の dataProvider からピクセル情報を取得して色を取り、その色をジオメトリに渡し配置するだけ。

 

UIImage から画像の色を取得する

今回は UIImage のエクステンションを作成。
UIImage を CGImage にして dataProvider からものデータを取る。
あとは CFDataGetBytes からデータを配列に変換する。

そのままだと配列に値が順番で詰め込まれる。
わかりやすくするため RGBA でごとに分けて多次元配列にしている。

extension UIImage {
    func getColorArray() -> [[UInt8]] {
        
        let imageRef = self.cgImage!
        
        let data = imageRef.dataProvider!.data
        let length = CFDataGetLength(data)
        var rawData = [UInt8](repeating: 0, count: length)
        CFDataGetBytes(data, CFRange(location: 0, length: length), &rawData)
        
        
        var colorArray = [[UInt8]]()
        
        let sepalatorLength = rawData.count / 4
        
        for i in 0..<sepalatorLength {
            let firstNumber = 4 * i
            let LastNumber = 4 * i + 3
            
            colorArray.append(
                Array(rawData[firstNumber...LastNumber])
            )
        }
        
        return colorArray
    }
}

 

ちなみに 0〜255 で値が変えるため、UIColor などで使用する際は 255 で割って 0 〜 1 の値にする必要がある。

また、RGBA の羅列となってしまうため、縦横のピクセル数は覚えていく必要がある。

あと、NSImage の場合はまた設定が異なるの注意。

 

色を渡し配置する

先ほどの配列を順番に読むと左上から横方向に色情報が取得できるため、それを適応するだけ。

今回は SCNNode の派生クラス SCNImageColorNode のイニシャライズで設定し、設定すると X, Z 座標で表示される。
設定するパラメータは UIImage、画像の縦横のピクセル数、ジオメトリ、ジオメトリ配置の際のマージンを設定している。

class SCNImageColorNode: SCNNode {
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    init(image:UIImage, imageWidth:UInt, imageHeight:UInt, geometry:SCNGeometry, geometoryOffsetX:Float = 0, geometoryOffsetZ:Float = 0){
        super.init()
        
        var array = image.getColorArray()

        let w = imageWidth
        let h = imageHeight
        
        let dx = (geometry.boundingBox.max.x - geometry.boundingBox.min.x)
        let dz = (geometry.boundingBox.max.z - geometry.boundingBox.min.z)
        
        for j in 0..<w {
            for k in 0..<h {
                let index = Int((j * w) + k)
                let node = SCNNode(geometry: geometry.copy() as? SCNGeometry)
                let material = SCNMaterial()
                
                material.lightingModel = .physicallyBased
                material.diffuse.contents = UIColor(
                    red: CGFloat(array[index][0]) / 255,
                    green: CGFloat(array[index][1]) / 255,
                    blue: CGFloat(array[index][2]) / 255,
                    alpha: CGFloat(array[index][3]) / 255
                )
                
                node.geometry?.materials = [material]
                
                let posX = Float(k) * (dx + geometoryOffsetX)
                let posZ = Float(j) * (dz + geometoryOffsetZ)
                
                node.simdPosition = float3(posX, 0, posZ)
                                
                self.addChildNode(node)
            }
        }
    }
    
}

 

UIViewController 側の設定例

let image = UIImage(named: "logo50")!
let box = SCNBox(width: 0.05, height: 0.05, length: 0.05, chamferRadius: 0)
        
let imageToGeoNode = SCNImageColorNode(image: image, imageWidth: 50, imageHeight: 50, geometry: box, geometoryOffsetX: 0.05, geometoryOffsetZ: 0.05)
        
scene.rootNode.addChildNode(imageToGeoNode)

 

雑につくっているので適当に手直しした方が良いかと思われる。

 

おまけ:アニメーションを設定する

本来は SCNImageColorNode の色を取得するループ内でアニメーションを設定した方が無駄な処理がないのだが、
汎用性を考えて UIViewController の SCNImageColorNode の小ノード調べ SCNAction を設定している。

var countUp = 0

for i in 0 ..< imageToGeoNode.childNodes.count {
    let chiledNode = imageToGeoNode.childNodes[i]
    
    if i % 50 == 49 { countUp += 1 }
    let count = i % 50 + countUp
    
    let posX = chiledNode.position.x
    let posZ = chiledNode.position.z
    
    let firstWait:TimeInterval = Double(count) * 0.01
    let endWait:TimeInterval = Double((50*50) - count) * 0.0025
    
    let move1 = SCNAction.move(to: SCNVector3(posX, 3.0, posZ), duration: 0.5)
    let move2 = SCNAction.move(to: SCNVector3(posX, 1.0, posZ), duration: 0.5)
    let move3 = SCNAction.move(to: SCNVector3(posX, 2.0, posZ), duration: 0.5)
    let move4 = SCNAction.move(to: SCNVector3(posX, 0.0, posZ), duration: 0.5)
    move1.timingMode = .easeOut
    move2.timingMode = .easeIn
    move3.timingMode = .easeOut
    move4.timingMode = .easeIn
    
    chiledNode.runAction(
        SCNAction.repeatForever(
            SCNAction.sequence([
                SCNAction.wait(duration:firstWait),
                move1,
                move2,
                move3,
                SCNAction.wait(duration: endWait),
                move4,
                SCNAction.wait(duration: endWait)
                ])
        )
    )
}

 

サンプルコード

github.com

 

まとめ

SceneKit の場合、テクスチャの色からパーティクルの色を設定することができないため、試しにジオメトリでやってみたが、
総ピクセルが 〜3K ぐらいまでなら XS では行けそうな感じではある。

また、同じ色であるならジオメトリを再利用できるので、色から調べジオメトリを新規に作成しない様にすると負荷が軽くなると思われる。