我正在使用Metal,我希望用户能够点击屏幕上的某些对象。我使用了轻拍手势识别器,因此我有一个CGPoint,但我不知道如何找到该对象。有没有办法获得金属的屏幕坐标,或者将CGPoint转换为金属坐标空间?
答案 0 :(得分:0)
我最终采用了光线追踪技术。我为每个物体使用了一个边界球体,并计算了光线是否与它相交,以及光线与光线的原点相距多远,光线来自相机通过屏幕上的点击点。代码如下:
var location = gestureRecognizer.locationInView(self.view)
var proj_matrix = projectionMatrix.copy()
var view_matrix = worldMatrix.copy()
var x = (2.0 * location.x) / self.view.bounds.size.width - 1.0;
var y = 1.0 - (2.0 * location.y) / self.view.bounds.size.height;
var newLocation = simpleVertex(x: Float(x), y: Float(y), z: Float(-1.0))
var projSpaceLoc = GLKMatrix4MultiplyVector4(GLKMatrix4Invert(proj_matrix.matrix(), nil), GLKVector4Make(newLocation.x, newLocation.y, newLocation.z, 1.0))
projSpaceLoc = GLKVector4Make(projSpaceLoc.x, projSpaceLoc.y, -1.0, 0.0)
var viewSpaceLoc = GLKMatrix4MultiplyVector4(GLKMatrix4Invert(view_matrix.matrix(), nil), projSpaceLoc)
GLKVector4Normalize(viewSpaceLoc)
//tappable is an array of nodes that can be tapped
for node in tappable {
var r: Float = node.r //this is the radius of the bounding sphere for that node
var c: GLKVector4 = node.origin //this is the origin of the bounding sphere
var little_c = GLKVector4DotProduct(c, c) - powf(r, 2)
var b = GLKVector4DotProduct(viewSpaceLoc, c)
var discriminant = powf(b, 2) - little_c
//If the discriminant is positive, their are two points of intersection, if it is 0, one point, and if it is negative, no points.
if (discriminant >= 0) {
var t_1 = (Float(-1.0)*b) + sqrtf(discriminant)
var t_2 = (Float(-1.0)*b) - sqrtf(discriminant)
if (intersect != nil) {
if (min(t_1, t_2) < intersect.intersect_point) {
intersect = (node, min(t_1, t_2))
}
} else {
intersect = (node, min(t_1, t_2))
}
}
}