我假设您指的是以下方法:
- (void)drawRect:(CGRect)rect
{
if (placesOfInterestCoordinates == nil) {
return;
}
mat4f_t projectionCameraTransform;
multiplyMatrixAndMatrix(projectionCameraTransform, projectionTransform, cameraTransform);
int i = 0;
for (PlaceOfInterest *poi in [placesOfInterest objectEnumerator]) {
vec4f_t v;
multiplyMatrixAndVector(v, projectionCameraTransform, placesOfInterestCoordinates[i]);
float x = (v[0] / v[3] + 1.0f) * 0.5f;
float y = (v[1] / v[3] + 1.0f) * 0.5f;
if (v[2] < 0.0f) {
poi.view.center = CGPointMake(x*self.bounds.size.width, self.bounds.size.height-y*self.bounds.size.height);
poi.view.hidden = NO;
} else {
poi.view.hidden = YES;
}
i++;
}
}
这是在感兴趣的地方执行类似于 OpenGL 的顶点变换,以检查它们是否在可视截锥体中。截锥体是在以下行中创建的:
createProjectionMatrix(projectionTransform, 60.0f*DEGREES_TO_RADIANS, self.bounds.size.width*1.0f / self.bounds.size.height, 0.25f, 1000.0f);
这将设置一个具有 60 度视场的截锥体、一个 0.25 的近剪裁平面和一个 1000 的远剪裁平面。然后,任何超过 1000 个单位的兴趣点都将不可见。
因此,要逐步执行代码,首先将设置截锥体的投影矩阵和相机视图矩阵相乘,相机视图矩阵只是简单地旋转对象,使其相对于相机正确向上。然后,对于每个感兴趣的地方,其位置乘以 viewProjection 矩阵。这会将感兴趣地点的位置投影到视锥中,应用旋转和透视。
接下来的两行将转换后的地点位置转换为所谓的标准化设备坐标。 4 分量向量需要折叠到 3 维空间,这是通过将其投影到平面 w == 1 上,将向量除以其 w 分量 v[3] 来实现的。然后可以通过检查其坐标是否位于边长为 2 且原点为 [0, 0, 0] 的立方体中来确定该点是否位于投影平截头体内。在这种情况下,x 和 y 坐标从 [-1 1] 到 [0 1] 范围内有偏差,以匹配 UIKit 坐标系,方法是加 1 并除以 2。
接下来,检查v[2]分量z是否大于0。这实际上是不正确的,因为它没有被偏置,应该检查它是否大于-1。这将检测感兴趣的地方是否在投影平截头体的前半部分,如果是,则该对象被视为可见并显示。
如果您不熟悉顶点投影和坐标系,这是一个庞大的主题,学习曲线相当陡峭。然而,网上有很多材料涵盖它,这里有几个链接可以帮助您入门:
http://www.falloutsoftware.com/tutorials/gl/gl0.htm
http://www.opengl.org/wiki/Vertex_Transformation
祝你好运//