gpt4 book ai didi

opengl-es - 如何从 Projection 和 ModelView 矩阵中获取 CATransform3D?

转载 作者:行者123 更新时间:2023-12-04 13:34:45 24 4
gpt4 key购买 nike

全部,
我有一个 iphone 项目,它使用 OpenGL-ES 为给定的模型 View 矩阵和给定的投影矩阵绘制 3D 模型。我需要用 CALayer 替换 3D 模型,所以我将模型 View 矩阵的值放入 CATransform3D 结构中并将其分配给 layer.transform .它运行良好,图层可见并按预期在屏幕上移动,但一段时间后我意识到我的图层行为不够精确,我应该考虑投影矩阵。然后出现了一个问题:当我简单地连接两个矩阵时,我的层看起来很奇怪(它非常小,大约 2 个像素,而它应该是 300 左右,因为它很远)或者根本不可见。我该如何解决?

这是一段代码:

- (void)adjustImageObjectWithUserInfo:(NSDictionary *)userInfo
{
NSNumber *objectID = [userInfo objectForKey:kObjectIDKey];
CALayer *layer = [self.imageLayers objectForKey:objectID];
if (!layer) { return; }

CATransform3D transform = CATransform3DIdentity;
NSArray *modelViewMatrix = [userInfo objectForKey:kModelViewMatrixKey];

// Get raw model view matrix;
CGFloat *p = (CGFloat *)&transform;
for (int i = 0; i < 16; ++i)
{
*p = [[modelViewMatrix objectAtIndex:i] floatValue];
++p;
}

// Rotate around +z for Pi/2
transform = CATransform3DConcat(transform, CATransform3DMakeRotation(M_PI_2, 0, 0, 1));

// Project with projection matrix
transform = CATransform3DConcat(transform, _projectionMatrix);

layer.transform = transform;
}

任何帮助将不胜感激。

最佳答案

我最近遇到了这个确切的问题(我也在使用 ARToolKit),我很失望地看到你没有找到答案。我想你现在已经继续前进了,但我想通了,我将它发布给任何其他可能遇到同样问题的迷失灵魂。

对我来说最令人困惑的是,每个人都在谈论通过将 m34 变量设置为一个小的负数来进行 CALayer 透视变换。尽管这确实有效,但它的信息量并不大。我最终意识到,变换的工作原理与其他变换完全一样,它是齐次坐标的列主变换矩阵。唯一的特殊情况是它必须结合模型 View 和投影矩阵,然后在一个矩阵中缩放到 openGL 视口(viewport)的大小。我首先尝试使用 m34 是一个小的负数的风格的矩阵,如更详细的解释 here但最终切换到开放式 GL 样式透视变换,如 here 所述.他们实际上是 equivalent对彼此而言,它们只是代表了对转换的不同思考方式。

在我们的例子中,我们试图使 CALayer 变换完全复制一个开放的 GL 变换。所需要的只是将模型 View 、投影和缩放矩阵相乘并翻转 y 轴以说明设备屏幕原点位于左上角而 open GL 位于左下角的事实。只要图层 anchor 在 (.5,.5) 并且它的位置正好在屏幕的中心,结果将与 open 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 View 大小并使用它们为 CALayer 生成正确的变换。 CALayer 大小应以 open GL 场景的单位指定。 OpenGL 视口(viewport)实际上包含 4 个变量,[xoffset,yoffset,x,y] 但前两个无关紧要,因为 CALayer 的 Origin 位于屏幕中央以对应 OpenGL 3d Origin。

只需将 Matrix 替换为您可以访问的任何通用 4x4 列主要矩阵类。只要确保你以正确的顺序乘以你的矩阵,任何事情都会奏效。所有这一切本质上都是在复制 OpenGL 管道(减去裁剪)。

关于opengl-es - 如何从 Projection 和 ModelView 矩阵中获取 CATransform3D?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6045502/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com