私は最近、まさにこの問題に遭遇し (私も ARToolKit を使用していました)、あなたが答えを見つけられなかったことに非常に失望しました。あなたは今先に進んだと思いますが、私はそれを理解し、この同じ問題を乗り越える可能性のある他の失われた魂のために投稿しています.
私にとって最も混乱したのは、m34 変数を小さな負の数に設定することで CALayer パースペクティブ トランスフォームを作成することについて誰もが話していることです。それは機能しますが、まったく有益ではありません。私が最終的に気付いたのは、変換が他のすべての変換とまったく同じように機能することです。これは、同次座標の列主要変換行列です。唯一の特殊なケースは、モデル ビューと射影マトリックスを組み合わせてから、openGL ビューポートのサイズにすべて 1 つのマトリックスでスケーリングする必要があることです。ここで詳細に説明されているように、m34 が小さな負の数であるスタイルでマトリックスを使用することから始めましたが、最終的にここで説明されているようにオープン GL スタイルの透視変換に切り替えました。それらは実際には同等です相互に、それらは変換についてのさまざまな考え方を表しているだけです。
私たちの場合、CALayer 変換がオープン GL 変換を正確に複製するようにしようとしています。必要なのは、モデル ビュー、投影、およびスケーリング マトリックスを乗算し、y 軸を反転して、デバイス画面の原点が左上であり、開いている GL が左下であるという事実を説明することだけです。レイヤー アンカーが (.5,.5) にあり、その位置が画面のちょうど中央にある限り、結果は開いている GL の変換と同じになります。
void attach_CALayer_to_marker(CATransform3D* transform, Matrix4 modelView, Matrix4 openGL_projection, Vector2 GLViewportSize)
{
//Important: This function assumes that the CA layer has its origin in the
//exact center of the screen.
Matrix4 flipY = { 1, 0,0,0,
0,-1,0,0,
0, 0,1,0,
0, 0,0,1};
//instead of -1 to 1 we want our result to go from -width/2 to width/2, same
//for height
CGFloat ScreenScale = [[UIScreen mainScreen] scale];
float xscl = GLViewportSize.x/ScreenScale/2;
float yscl = GLViewportSize.y/ScreenScale/2;
//The open GL perspective matrix projects onto a 2x2x2 cube. To get it onto the
//device screen it needs to be scaled to the correct size but
//maintaining the aspect ratio specified by the open GL window.
Matrix4 scalingMatrix = {xscl,0 ,0,0,
0, yscl,0,0,
0, 0 ,1,0,
0, 0 ,0,1};
//Open GL measures y from the bottom and CALayers measure from the top so at the
//end the entire projection must be flipped over the xz plane.
//When that happens the contents of the CALayer will get flipped upside down.
//To correct for that they are flipped updside down at the very beginning,
//they will then be flipped right side up at the end.
Matrix flipped = MatrixMakeFromProduct(modelView, flipY);
Matrix unscaled = MatrixMakeFromProduct(openGL_projection, flipped);
Matrix scaled = MatrixMakeFromProduct(scalingMatrix, unscaled);
//flip over xz plane to move origin to bottom instead of top
Matrix Final = SiMatrix4MakeFromProduct(flipY, scaled);
*transform = convert_your_matrix_object_to_CATransform3D(Final);
}
この関数は、open GLprojection と openGL ビュー サイズを取得し、それらを使用して CALayer の正しい変換を生成します。CALayer のサイズは、開いている GL シーンの単位で指定する必要があります。OpenGL ビューポートには実際には [xoffset,yoffset,x,y] の 4 つの変数が含まれていますが、最初の 2 つは関係ありません。これは、CALayer の Origin が OpenGL 3d Origin に対応するように画面の中央に配置されているためです。
Matrix を、アクセスできる一般的な 4x4 列の主要な行列クラスに置き換えるだけです。マトリックスを正しい順序で乗算することを確認するだけで、何でも機能します。これが本質的に行っていることは、OpenGL パイプラインを複製することだけです (クリッピングを除く)。