頭と尻尾はくれてやる!

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


ARKitのARFaceGeometryで得た頂点座標を2D座標に変換する

4要素のうちの3要素で頂点座標データ(SCNGeometrySourceオブジェクト)を作る
↑この続き。
頂点を表示させることができたのでこの頂点を移動させたい。顔を変形させて遊んでみるためだ。

ARFaceGeometryのverticesプロパティで顔の頂点の座標データ列を得ることができるが、これらの頂点はデバイスの画面上(2D)ではどの位置に来るのか?を計算できるようになりたい。

シェーダでやってもいいのだけど、まずは正しく理解するためにCPU側でやってみた。

頂点番号がvertexIteの頂点はiPhoneの画面のどこに表示されるのか?を計算する。
{
    …
    ARFaceGeometry *arFaceGeometry = faceAnchor.geometry;
    const simd_float3 *vertices = arFaceGeometry.vertices;
    simd_float3 pos3 = vertices[vertexIte];// —(1)
    simd_float4 position = simd_make_float4(pos3 , 1.0);

    simd_float4x4 modelMatrix = faceAnchor.transform;// —(2)

    ARFrame *frame = arsceneView.session.currentFrame;
    ARCamera *arcamera = frame.camera;
    simd_float4x4 viewMatrix = [arcamera viewMatrixForOrientation:UIInterfaceOrientationPortrait];// —(3)

    SCNCamera *camera = arsceneView.pointOfView.camera;
    SCNMatrix4 cameraProjectionMatrix = camera.projectionTransform;
    simd_float4x4 projectionMatrix = SCNMatrix4ToMat4(cameraProjectionMatrix);// —(4)

    simd_float4x4 matrices = matrix_multiply(viewMatrix,modelMatrix);
    matrices = matrix_multiply(projectionMatrix,matrices);// —(5)
    
    position = matrix_multiply(matrices, position);
    position = position / position.w;// —(6)

    float xx = (position.x+1.0)/2.0 * arsceneView.frame.size.width;
    float yy = (-position.y+1.0)/2.0 * arsceneView.frame.size.height;// —(7)

    marker.center = CGPointMake(xx, yy);// —(8)
}
(1)頂点番号がvertexIteの頂点の座標を得る。この座標は表情によって変化する。
(2)顔自体の位置や向きによるマトリックスを得る。
(3)カメラを考慮するマトリックスを得る。
(4)プロジェクションマトリックスで2次元座標を得る。ARCameraのプロパティにその名も projectionMatrix というのがあるのだが、値が微妙に異なり実際少しずれてしまったので上記の方でよいと思う。
(5)順にかけて1つのマトリックスを得る。
(6)この計算により-1から1の2次元座標を得られる。
(7)iPhoneの画面ではどこかを計算。iPhoneのUIView系は左上が原点なのでy座標にはマイナスがかかっている。
(8)指定した頂点に何か目印になるUIViewオブジェクト(ここではmarker)を移動させるようにして動作確認を行った。


↑その実行結果。
口の上部に赤くした頂点があり、画面をタップすると(画面ではタップしたことは見えないが)薄い四角形(UIViewオブジェクト)が移動している。

↑こちらはその応用で、マーカーの位置と全頂点の画面上での位置との距離をCPU側で計算し、その値をシェーダに渡して近いほどその頂点をずらしている。前半は鼻が高く、後半は口付近が大きく飛び出している。
スポンサーサイト

<< simd_float4x4の作成方法  TopPage  ポケモンGOのいつでも冒険モードのためにスマートウォッチを購入したが >>

コメント


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

トラックバック

トラックバックURL
https://ringsbell.blog.fc2.com/tb.php/1277-9556fe27




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

FC2Ad