FC2ブログ

頭と尻尾はくれてやる!

パソコンおやじのiPhoneアプリ・サイト作成・運営日記


Game Centerの認証に成功してるのにお帰りなさい画面が出ない

最近Game Center / GameKitを使うアプリについて調べている。
Game Centerを使う場合、通常アプリと違って事前にやることがある。

Game Center機能を実装する - Qiita

↑こちらのページなどを参考にしつつ、
Developer PortalでApp IDを追加
App Store ConnectでGame Centerを使う
などを設定。

Xcodeで新規のプロジェクトを作成。

まずは認証のチェックをしたい。Game Center対応アプリなら起動直後に画面上部にいつも出てくるあの画面。

Game Centerのおかえりなさい画面

↑このお帰りなさい画面(※)。これを表示させたい。

authenticateHandler - GKLocalPlayer | Apple Developer Documentation
↑リファレンスにあるようなごくシンプルなコードで確認してみた。
認証は成功しているはずなのだが、どういうわけかお帰りなさい画面が出てこない。


自分のiPhone実機で検証をしていたのだが、この時点でアカウントがテスターじゃないとダメなのか?ということでiPhone実機のユーザーを変更、、、
したくないよな、なるべく。
なのでiOSシミュレータでテスターのアカウントでログイン(自動的にGame Centerはオンになっていた)。
そのシミュレータで起動すると

Game CenterのWelcome back画面

↑ちゃんとWelcome back、お帰りなさいが出た!
つまりGame Centerアプリ開発するなら、デバイスはテスト用のアカウントを使ってログインしておくべき、ということか。


※ このスクショは最近やってる「1000m Zombie Escape!」というゲーム画面の上部。



===== 修正・追記(12/11) =====

Game CenterのWelcome back画面

↑勘違いだったようで、テストアカウントではない実機デバイスでもお帰りなさい画面が出た。

結論:テスト用アカウントじゃなくてもお帰りなさい画面は出る




TrueDepthカメラとARKitを使う画面の背景をキューブマッピングで設定する

Objective-CでCGAffineTransformからSCNMatrix4へ変換する
↑ここでも少し触れているが、Appleのサンプルコード Creating Face-Based AR Experiences で自分の顔の位置・姿勢、目と口の開け具合を反映してロボットの顔を表示するのがある。

FaceTracking中のスクショ

↑こういうサンプルアプリ。

このようなアプリの場合、表示にはSCNViewのサブクラスであるARSCNViewクラスが使われてる。
TrueDepth cameraを使うARFaceTrackingConfigurationでsessionをスタートすると画面の背景には自動的に(特に記述する必要もなく)フロントカメラで撮影した画像が画面に表示される。

アプリの用途によってはこのフロントカメラで得た画像は不要で、SceneKitで描いた風景なんかを描いてみたい、という場合もあるかもしれない。
ということで背景をキューブマッピングで指定してみた。
{
    // Create a new scene
    SCNScene *scene = [SCNScene sceneNamed:@"art.scnassets/ship.scn”];//—(1)

    // Set the scene to the view
    self.sceneView.scene = scene;//—(2)

    scene.background.contents = @[@"sky_front.png", @"sky_front.png", @"sky_top.png", @"sky_front.png", @"sky_front.png", @"sky_front.png”];//—(3)
}
↑SceneKitを使うプロジェクトを作成すると(1),(2)のような記述がある。
その下に(3)のような6方向の画像を指定する。これは別にARSCNViewとか関係なくSceneKitでは通常の記述だ。
挙動を見たいというだけなので2種類の画像しか使っていないが😁
その結果が↓こちら。


デバイスの方向に従って背景画像が変わっている。

なお、現在のところ上記コードの(3)を(1)と(2)の間に置くとうまく背景が設定できない(そのうち直るかもしれないけど)。


Xcode 10.1
iOS 12.1


Objective-CでCGAffineTransformからSCNMatrix4へ変換する

Creating Face-Based AR Experiences | Apple Developer Documentation
↑APPLE公式のサンプルコード Creating Face-Based AR Experiences (プロジェクト名はARKitFaceExample)でTrueDepth Cameraを使うコードの勉強のためSwiftで書かれているコードをObjective-Cに書き直しつつ”写経”している。
{
        let affineTransform = frame.displayTransform(for: .portrait, viewportSize: sceneView.bounds.size)//—(1)
        let transform = SCNMatrix4(affineTransform)//—(2)
        faceGeometry.setValue(SCNMatrix4Invert(transform), forKey: "displayTransform”)//—(3)
}
↑そこにこのような、SCNMatrix4のtransformをシェーダ(shader modifierと言うべき?)に渡すような記述がVideoTexturedFace(顔が大きくなるやつ)にある。
(1)でCGAffineTransformのaffineTransformを得ている。このCGAffineTransformは2D画像を変換するもの。
(2)でそれをSCNMatrix4へ変換している。
(3)さらにその逆行列をシェーダに渡す。

困ったことにObjective-Cでは(2)のように簡単にCGAffineTransformからSCNMatrix4へ変換することができない。
ということでなんとかしたいのだが、、、

【解決策その1】
{
    CGAffineTransform affineTransform = [frame displayTransformForOrientation:UIInterfaceOrientationPortrait viewportSize:size];//—(4)
    CATransform3D caTransform = CATransform3DMakeAffineTransform(affineTransform);//—(5)

    SCNMatrix4 transform;
    transform.m11 = caTransform.m11;
    transform.m12 = caTransform.m12;
    transform.m13 = caTransform.m13;
    transform.m14 = caTransform.m14;
    transform.m21 = caTransform.m21;
    transform.m22 = caTransform.m22;
    transform.m23 = caTransform.m23;
    transform.m24 = caTransform.m24;
    transform.m31 = caTransform.m31;
    transform.m32 = caTransform.m32;
    transform.m33 = caTransform.m33;
    transform.m34 = caTransform.m34;
    transform.m41 = caTransform.m41;
    transform.m42 = caTransform.m42;
    transform.m43 = caTransform.m43;
    transform.m44 = caTransform.m44;

    transform = SCNMatrix4Invert(transform);
}
↑(4)でCGAffineTransformを得ている。
(5)で2DのCGAffineTransformを3DのCATransform3Dに変換(※)。
これをSCNMatrix4にしたいわけだが、、、後は単に入れるだけのべたな方法だ。


【解決策その2】
{
    CATransform3D caTransform = CATransform3DMakeAffineTransform(affineTransform);

    NSValue *value = [NSValue valueWithCATransform3D:caTransform];
    SCNMatrix4 transform = [value  SCNMatrix4Value];
}
↑CATransform3Dに変換するのまでは先ほどと同じ。
それをNSValue経由で変換してやる。すっきりした。


以上のようにすれば、CGAffineTransformからSCNMatrix4へ変換することはできる。


【おまけ】
{
    CATransform3D caTransform = CATransform3DMakeAffineTransform(affineTransform);//—(6)
    NSValue *value = [NSValue valueWithCATransform3D:CATransform3DInvert(caTransform)];//—(7)
    [faceGeometry setValue:value forKey:@"displayTransform”];//—(8)
}
↑でもシェーダに渡すのにNSValueオブジェクトで渡せるのでSCNMatrix4を使わなくていいことに気付いた。
(6)CATransform3Dに変換するのまでは先ほどと同じ。
(7)で(逆行列にした)CATransform3DをNSValueにして
(8)でシェーダに渡す。
これが一番すっきりする。


※参考サイト
how to convert the CGAffineTransform to CGTransform3D? - Stack Overflow


iPhone X系の背面デュアルカメラで「電脳コイル」ごっこがしたい

iPhoneには背面に広角と望遠のレンズを持つ機種があるが、この二つのカメラから同時に動画を得たいと思いいろいろと試してみた。
iPhone 7,8のPlusだと二つのレンズが(縦に持った場合)横だったが、iPhone X系から縦に並ぶようになった。
つまり、これをLandscapeにするとカメラは横に並ぶ。
この二つのカメラからの動画をそれぞれ並べ、VRゴーグルで見ると風景が立体に見えるはず(もちろん一般に販売されてるVRゴーグルにはiPhoneの背面カメラ用の穴なんてないから穴を開ける必要がある)。
さらにARKitで現在のカメラ位置や姿勢を得て、現実の風景にSceneKitで物体を重ねて表示させたら「電脳コイル」ごっこができるんじゃね?!

VRアプリのスクリーンショット

↑これは以前リリースしたiOSアプリでVRゴーグルで使うものなんだけど、こんな感じで左右微妙に違うCGのオブジェクトを表示されれば、景色もCGも立体で見ることができる!デンスケが俺の部屋をうろうろと歩いたりするんだ!
APPLEもそのためにカメラの位置を変更したんだよね!
などと妄想したのだった。


デンスケのぬいぐるみ

↑ちなみにデンスケというのは「電脳コイル」ってアニメに出てくるキャラで画像はそのぬいぐるみ。



そんなわけで二つの背面カメラからのビデオ情報を得たいのだが、、、

- (void)captureOutput:(AVCaptureOutput *)captureOutput
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
fromConnection:(AVCaptureConnection *)connection;
↑AVCaptureVideoDataOutputSampleBufferDelegateのこのメソッドが双方のカメラごとにコールされたらなんとかなるはずだ。sampleBufferから画像は生成できるから。

基本的にはAVCaptureSessionオブジェクトに、AVCaptureDeviceInputオブジェクトとAVCaptureVideoDataOutputオブジェクトをaddするので、これらをカメラごとに複数用意するなどいろいろ試行錯誤したのだが、、、

実行結果スクショ

↑二つ作成したAVCaptureVideoDataOutputオブジェクトのポインタをログで確認。
上記delegateメソッド内でコールされてるのはどっちのかを確認している。なおAVCaptureVideoDataOutputはAVCaptureOutputのサブクラス。
よく見ると最初だけ片方のoutputが来てるが、後はずっともう片方のデータしか来ていない。

現在のiOS 12.1では無理っぽい。それらしいプロパティ、メソッドなさそうだし。

iPhone背面のデュアルカメラで同時に写真を得る
↑ここでも書いてるけどデュアルカメラで同時に静止画が撮影できるようになったのがiOS 11.0からだしなあ。まだ時間かかるのかもしれない。

ios - iPhone 7 Plus - AVFoundation dual camera - Stack Overflow
↑ビデオは無理だよって書いてる。公式フォーラムの”中の人”ではないので参考までに。



iOS 12.1
Xcode 10.1


iPhone背面のデュアルカメラで同時に写真を得る

2年くらい前に購入したのがiPhone 7 Plus。このデバイスにはリアカメラに広角と望遠の二つのレンズがあってその視差から背景をぼかせるポートレートモードが実装されていた。
私も同時にカメラの画像を得たいといろいろと調べていたのだが、ユーザーが使えるフレームワークでは同時に両方のレンズで画像を得ることはできそうになかった。
公式のフォーラムでもだめなのかねえ、使いたいよねえ、みたいな書き込みがあったと思う。
ここまでがiOS 10の話。

その1年後(去年の秋くらいか)にARKitを引き連れてiOS11がリリースされたんだけど、地味にデュアルカメラ周りのAPIが追加されてた。
そう、デュアルカメラで二つのレンズからの画像を同時に取得できるようになっていたのだ!
と言っても自分は全然ウォッチしてなくてつい最近知ったんだけど。

そんなわけで1年遅れのネタを2年前のコードをベースに遊んでみた。


ios - Capture frames from both cameras (TelePhoto and WideAngle) in the same time - Stack Overflow
↑この記事がとても参考になった。
AVCaptureDeviceオブジェクトは1つでいい!
デバイスタイプはAVCaptureDeviceTypeBuiltInDualCameraでOK(望遠、広角の二つなのか?と思っていた)。

ところが
AVCapturePhotoOutput *output;//インスタンス

output.isDualCameraDualPhotoDeliverySupported
↑これがなぜか真にならない。サポートされていない?なので強引に
output.dualCameraDualPhotoDeliveryEnabled = YES;
とすると
Dual Camera dual photo delivery is not supported in this configuration'
というメッセージを吐いて落ちる。

iPhone 7 Plusだとダメなの?と調べるとiPhone 8 Plusだけどダメ、iPhone Xだけどダメって書き込みが見つかる。公式フォーラムには1年くらい前にバグレポも出されているとある。
どういうことかといろいろと試していたんだが、、、
AVCaptureSession *session;//インスタンス

{
    [session addOutput:output];//—(1)

    if (output.isDualCameraDualPhotoDeliverySupported) {
            output.dualCameraDualPhotoDeliveryEnabled = YES;
        } else {
            NSLog(@"DualCameraDualPhotoDelivery is not supported!");
        }

    //[session addOutput:output];//—(2)
}
↑元々(2)の位置でsessionにaddOutput: しており、その前でデュアルカメラ周りの設定をしていた。この順番を変えてaddOutput: を(1)の位置に持ってきたらすんなりと設定ができたのだ。
そのうち修正されるだろうけど。


いざ、両方のレンズから撮影した画像をライブラリに保存してみたところ、、、

iPhone 7 Plusの望遠レンズによる画像 iPhone 7 Plusの広角レンズによる画像

↑画像が2枚保存されている!これちゃんと視差あるんだよね?ぱっと見ただけじゃよくわからないなあと思って画像編集ソフトで重ねてみた。

視差確認画像1
視差確認画像2

↑iPhoneの文字部分をよく見ると、’i’をぴったり合わせると’e’のところにずれが生じ、その逆も同じようになってる。まったく同じ画像というわけではないことがわかる。
こういう微妙な差から深度を計算していたんだねえ。凄い!

ちなみに画像の箱は今日届いたばかりのiPhone XS Max。この後、7 Plusから機種変更だ。


iOS 12.1







Copyright ©頭と尻尾はくれてやる!. Powered by FC2 Blog. Template by eriraha.

FC2Ad