著者名が「magicien
31〜40件目 / 226件
前へ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 次へ

 glTF用QuickLookプラグインを作った / magicien 

image QuickLookプラグインの作り方が分かったところで、早速glTFビューアを作ってみた。
GLTFQuickLook - macOS QuickLook plugin for glTF files


インストール方法

Homebrewでインストールする場合

ターミナルで、
brew cask install gltfquicklook
を実行する

手動でインストールする場合

  1. GitHubのReleasesからzipファイル(GLTFQuickLook_vX.X.X)をダウンロードする
  2. zip内の GLTFQuickLook.qlgenerator を /Library/QuickLook (全ユーザ用)か ~/Library/QuickLook(個別ユーザ用)にコピーする
  3. ターミナルで、qlmanage -r コマンドを実行(あるいは、OS再起動)して、QuickLookプラグインのリロードを行う。

使い方

Finderでファイルを選ぶと、プレビュー欄に3Dモデルが表示されるよ!
ファイル選択中にスペースキーを押すと、大きなプレビュー画面が表示されるよ!
※あくまで静止画なので、ドラッグしてもモデルは動かせないよ!
※マウスでモデルを動かせるよ!

開発メモ

QuickLookプラグインでSwiftのフレームワークを使うには、プラグインにSwiftの標準ライブラリを同梱してあげる必要があるようだ。Xcodeで Build Settings > Build Options > Always Embed Swift Standard Libraries を Yes に設定すればOK。
また、追加したフレームワークが、パッケージの Resources というディレクトリに入ってしまうようなので、Build Settings > Linking > Runpath Search Paths に @loader_path/../Resources/ を追加した。

OS標準のscn用QuickLookだと、モデルをグリグリ動かせるんだけど、どうやっているのかなぁ。
scnファイル形式で書き出してQuickLookのAPIに丸投げしたら動いた!
        GLTFSceneSource *source = [[GLTFSceneSource alloc] initWithURL:(__bridge NSURL*)url options:nil];
        SCNScene *scene = [source sceneWithOptions:nil error:nil];

        NSData *scnData = [NSKeyedArchiver archivedDataWithRootObject:scene];
        CFStringRef contentTypeUTI = CFSTR("com.apple.scenekit.scene");
        
        QLPreviewRequestSetDataRepresentation(preview, (__bridge CFDataRef)(scnData), contentTypeUTI, options);

2017/11/19(Sun) 07:20:37

 SwiftのフレームワークをObjective-Cで使えるようにするには / magicien 

各クラスの前に @objcMembers を付けるだけ!
ただ、[MyClass?] みたいに、OptionalのArrayはObjective-Cに変換できないようだ。
ファイルサイズが大きくなってしまう点も気にかけておこう。


image ファイルのプレビュー機能である QuickLook のプラグインは、CかObjective-Cで書かなければならない。プラグインがカーネル側で動くことに関係していそうだが、理由はいまいちよくわからない。
MMDSceneKitはSwiftで書いているので、MMD用のQuickLookを作るには、フレームワークをObjective-Cで書き直さないといけない、と思い込んでいたけれど、@objcMembers を付けたら、Objective-Cからでも問題なく使えた。

モデルが赤紫色で表示されるのは、シェーダでエラーが発生したとき。別ファイルのテクスチャが読み込めていないのかもしれない。いずれにせよ、QuickLook用プラグインでSwiftのフレームワークが使えることに気づいたのは、自分にとって大きな収穫だった。

そういえば、SCNSkinnerのバグレポートはサポートから返信があった。次のバージョンでは直っているといいなぁ。

2017/11/18(Sat) 04:49:22

 JSceneKitでobjファイル表示対応した / magicien 

image Polyなるサービスが始まったらしいと聞いて、JSceneKitで作りかけだったobjファイルの表示機能を実装した。例によって必要最低限の機能しか実装していないけれど、Polyからダウンロードできるobjファイルは概ね表示できるはず。


Polyにアップロードされているモデルを眺めていると、明らかに毛色の違うものがちらほら。どうやらVRで作られたものらしい。3Dモデルというと、直方体やカプセルのような形から始めて、ポリゴンを分割したり、凹凸を付けたりしていくのが一般的だと思うのだけれど、VRで作られたモデルは、まるで油絵のように、色の付いたポリゴンをいくつも重ねて作られていた。ポリゴン同士が連結していないので、隙間から向こうが見える。

露骨な三角形や四角形の組み合わせも折り紙のようで嫌いではないけれど、輪郭の曖昧なモデルも味があって良い。もちろん、VRを使わなくても同じ表現はできるのだろうが、VRがあるからこそ生まれた表現だろう。

2017/11/11(Sat) 04:59:09

 色々と手詰まり中 / magicien 

ここのところ色々なバグや問題に引っかかってあらゆるものが停滞している。以下、駄文。

iOSでclassの変数にアクセスすると、EXC_BAD_ACCESSエラーで落ちる

JSONDecoderで取得したデータにアクセスしようとすると、エラーで落ちる問題があって困惑している。
考えられる原因としては、
  • MainThread以外でJSONDecoderを使っているから?
  • Codableなclassをextendsして使っているから?
  • ARCの処理が変わった?どこかをweakとかunownedとかにしないといけないのか?
  • JSONDecoderかARCのバグ?
といった感じなのだけれど、よくわからない。コールスタックを見ると、こんな感じの見知らぬ関数が呼ばれていた。

  • materializeForSet
  • swift_beginAccess
  • insert
  • reportExclusivityConflict
JSONDecoderで取得したデータにアクセスした時に、排他アクセスチェックが行われ、問題があったのでデバッガにリポートを送信した帰りに変なメモリにアクセスして落ちているようだ。実際は、reportExclusivityConflictが終わり、insertから帰る寸前で何かをやらかしている。スタックに退避したデータをレジスタに書き戻す直前に何かごにょごにょやっているようなのだが、処理を追う気力が無かった...
まぁ元々の問題はどこかで変数書き込み処理がコンフリクトしていることらしいので、それを解決すれば、この問題も自ずと解決するはず。せめて、reportExclusivityConflictの出力がデバッガで受け取れれば良いのだが、その前にエラーで落ちてしまっているようで、原因の究明が難航している。

SCNSkinnerが使えなくなった

ベータ版を使っていた時は大丈夫だったのに。
SCNSkinnerを使うには、boneIndicesとboneWeightsを渡す必要があるのだが、boneIndicesにいつも通りUInt16のデータを渡すと、
[SceneKit] Error: Compiler error while building render pipeline state for node "(null)" (0x1016db2c0): Error Domain=CompilerError Code=2 "Vertex attribute skinningJoints(4) of type uint4 cannot be read using MTLAttributeFormatShort4" UserInfo={NSLocalizedDescription=Vertex attribute skinningJoints(4) of type uint4 cannot be read using MTLAttributeFormatShort4}
というエラーが出る。uint4は4バイトのunsigned intを4つセットにしたベクタ。要するに、2バイトじゃなくて4バイトのデータをくれ、ということなので、UInt32に変換してデータを渡してみると、
[SceneKit] Error: SCNSkinner: bone indices must be uint8 or uint16 (maximum of 2 bytes)
boneIndicesは最大2バイトまでだという。何を言っているのか。
SceneKitに渡せるのは2バイトまで。SceneKitの先にあるMetalに渡す必要があるのは4バイト。詰んだ。

追記:
GLTFQuickLookを作った時に偶然発見したんだけど、NSKeyedArchiverでSCNSceneをNSDataに変換した後、SCNSceneのイニシャライザにデータを渡したら、SCNSkinnerの問題を回避できた... とりあえず、バグが直るまではこれで対応しよう。

その他バグ

以前、いくつかのバグを報告をしたところ、1件だけ反応があり、最新のベータ版OSで再発するか試してくれ、と書いてあったので試したけれど、挙動が変わったものの問題は解決していなかった。報告用のログを集めるのが面倒なのと、ベータ版を使い続けるのが嫌になってダウングレードしてしまったので、返事をせず放置していたら、バグレポートがクローズされてしまった。残りのレポートは応答なし。バグを報告するのが億劫になってきた。でも、SCNSkinnerについてはなんとかしないと先に進めないので、適当に書いて送ろう。
2017/10/28(Sat) 05:39:06

 GitHubから取得したファイルをindexedDBに保存する / magicien 

ブラウザ(JavaScript)からGitHubのリポジトリのアーカイブを取得・展開するの続き。
展開したファイルをIndexedDBに保存する。


DBのオープンやデータの更新を要求すると、戻り値として IDBRequest のオブジェクトが返ってくる。このオブジェクトの onsuccess と onerror に関数を設定すると、処理が終わった時に呼び出される。ソースはこんな感じ。例によって検証していないので、typoとかバグとかあるかも。

リクエストを発行してからでないとコールバック関数が設定できないのは設計がおかしいんじゃなかろうか。
とりあえず、getResult関数でonsuccess、onerrorをPromiseでラップしておく。transactionの場合は、イベント名がちょっと違って、oncomplete、onerror、onabort になる。ディスクの空き容量が足りないと、QuotaExceededError が起きて onabort が呼び出される。手元のMacBook Airだとこのエラーが頻繁に起きる。
IndexedDBで使える容量はブラウザや状況(ディスクの空き容量)によって変わるようで、ひどい時はChromeで容量上限が10KBだった。おまえ、キャッシュとかswapとかで軽く数GB食いつぶすくせにIndexedDBには厳しすぎない?まぁ無いものは無いのでエラーを出して終了するしかない。Chromeを終了してディスクを解放してから再起動すると上限が1GBに増えていたりする。

2017/10/08(Sun) 07:46:30

 ブラウザ(JavaScript)からGitHubのリポジトリのアーカイブを取得・展開する / magicien 

需要がありそうで全く無い、ブラウザのJavaScriptで、GitHubからリポジトリをzipで落とす方法。

GitHubのAPIドキュメントによると、GET /repos/:owner/:repo/:archive_format/:ref でアーカイブがダウンロードできるらしい。
archive_formatは、zipball か tarball の二択。ref はブランチ名とかタグ名とか。リクエストを送ると、302のリダイレクトでダウンロードURLを教えてくれる(https://codeload.github.com/... とか)。

問題は、codeload.github.comがクロスドメインを許可していないこと。JavaScriptでダウンロードしようとすると、ブラウザ側で自主規制がかかって失敗する。仕方が無いので、サーバを経由してダウンロードさせることにする。サーバがGitHub Appのアクセストークンを持っているなら、プライベートなリポジトリもダウンロードできる(5分間だけ有効なダウンロードURLを教えてもらえる)ので、これが正しい方法なのだろう。

ソースコードはこんな感じ。実際に使っているものを抜粋・編集したものだけれど、未検証なので動かないかもしれない。
ここぞとばかりにasync/awaitを使ってみたが、.then.then.thenでも良いと思う。

続き:GitHubから取得したファイルをindexedDBに保存する

2017/10/06(Fri) 06:34:12

 Swift4.0でCodableなクラスを継承した場合の挙動 / magicien 

なんか想定と違ったので色々確認することにした。

結論から言うと、継承したクラスでは、init(from decoder: Decoder)を自分で実装しないとだめ。
継承元のクラスはinitを省略可。省略した場合でも、サブクラスからsuper.init(from:)を呼ぶとちゃんとパースしてくれる。

2017/10/03(Tue) 09:58:24

 ARKitの動画再アップ / magicien 

以前ニコニコ動画にアップしていた(その後削除した)ARKitの動画を再アップしました。


もはや今更な感じがするけれども。
Xcodeをバージョンアップしたら、UIColorの仕様がちょっと変わっていた。というかNSColorとほぼ同じになっていた。これでOSによる分岐が無くせるかも。むしろ今まで微妙にインタフェースが違ったのは嫌がらせか何かだったのか。

2017/09/27(Wed) 14:00:29

 Heroku/Node.js/ExpressでGitHub AppsのInstallation認証 / magicien 

GitHub Appsとしてリポジトリの操作が必要な場合は、Installation認証が必要。
ユーザは無関係の認証なので、サーバ・GitHub間だけで完結する。

ソースはこんな感じ。
Installation IDは、ユーザ認証のときに取得する必要がある。
ユーザとは無関係に操作できてしまうので、操作を要求しているユーザが対象のInstallationのアクセス権を持っているか確認が必要。

2017/09/15(Fri) 04:05:03

 新iPhone! / magicien 

既に色々と情報がリークしていましたが、ようやく新iPhoneが発表されましたね。

iPhone9が欠番になっちゃいましたが、8sの代わりに9が出たりするのかなぁ。Xも出ちゃったので以降のネーミングはmacOSみたいな感じになりそうですね。

個人的にはAnimojiが一番気になりました。顔認証技術をそうやって使うのかと。
そのうちMacBookにも同じ機能が付くのかなぁ。MMDの表情モーションを自分で演じて作るというのも面白いかもですね。
Dot Projectorというパーツが増えていたので、Kinectと同じようなことをしているんでしょう。Microsoftと何らかのやり取りがあったんでしょうか。ここら辺の技術はどこが持っているのか。
(追記:2013年にAppleがイスラエルのPrimeSenseという会社を買収していたようですね。Kinectのセンサーを作っていた会社らしいです。4年前からFaceIDの開発が進められていたってことですかね。対してKinectは生産終了...うーむ。iPhoneのDot Projectorで姿勢検知までできるようになると良いですね。)

もう一つ気になったのは、Apple TVとiPhoneのHDR対応。ディスプレイ側がHDRに対応するとなると、シェーダはどうやって書けば良いんでしょう。HDR対応有無でシェーダ書き分けるのとか面倒そう...

そういえば、Touch IDで他人がロックを解除できる確率は1/50,000とか言っていたけれど、結構確率高くないですか。まぁiPhoneに限らず、指紋認証機能を使っていると、自分の指なのになかなか認証が通らなかったり、他の人の指で解除できてしまったりということが多々あったので、あんまり信用できないか、精度を上げようとするとお金がかかる技術なのかなぁという印象があったのですが。
Face IDは、人工マスクでもロック解除できないことをテストしました、ということでしたが、サーモグラフィでも見ているんですかね。そのうち例によって顔認証をハックしちゃう人たちが現れるでしょう。

2017/09/13(Wed) 05:21:53