Недавно я столкнулся с этой проблемой (я также использовал ARToolKit), и я был очень разочарован, увидев, что вы не нашли ответ.Я полагаю, что вы пошли дальше, но я понял это и выкладываю это для любой другой потерянной души, которая может столкнуться с той же проблемой.
Самым запутанным для меня было то, что все говорят о том, чтобы преобразовать перспективу CALayer, установив для переменной m34 небольшое отрицательное число.Хотя это работает, это не очень информативно.В конце концов я понял, что преобразование работает точно так же, как любое другое преобразование, это матрица преобразования основных столбцов для однородных координат.Единственный особый случай - это то, что он должен объединить матрицу вида модели и проекции, а затем масштабировать до размера окна просмотра openGL, все в одной матрице.Я начал с попытки использовать матрицу в стиле, где 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);
}
Эта функция принимает открытоеGLprojection и openGL view size и использует их для генерации правильного преобразования для CALayer.Размер CALayer должен быть указан в единицах открытой сцены GL.Окно просмотра OpenGL на самом деле содержит 4 переменные [xoffset, yoffset, x, y], но первые две не имеют значения, потому что Origin of CALayer помещен в центр экрана, чтобы соответствовать OpenGL 3d Origin.
Просто замените Matrix любым классом основной матрицы 4x4, к которому у вас есть доступ.Все будет работать, просто убедитесь, что вы умножаете свои матрицы в правильном порядке.Все, что по сути дела, это репликация конвейера OpenGL (за исключением отсечения).