FC2ブログ

頭と尻尾はくれてやる!

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


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

<< 休暇村讃岐五色台のキャンプ場へ行ってきた  TopPage  Objective-CのプロジェクトからSwiftを使おうとしたらFile Not Found >>

コメント


管理者にだけ表示を許可する
 

トラックバック

トラックバックURL
http://ringsbell.blog117.fc2.com/tb.php/1253-9e2cba7e




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

FC2Ad