Я пытаюсь реализовать сбор с raycasting в OpenGL ES 2.0 для iPad-приложения. В частности, я хочу знать, какая ячейка карты, похожая на minecraft, состоит из квадратных ячеек с разной высотой, на которую пользователь нажал. Однако мой код не находит пересечения с любой ячейкой.Где я ошибался, пытаясь реализовать сбор с raycasting в OpenGL ES 2.0 для iOS?
В моем методе жест распознавателя, я сначала получить точку и видовых размеры
UITapGestureRecognizer* tapRecognizer = (UITapGestureRecognizer*) recognizer;
CGPoint tapLoc = [tapRecognizer locationInView: self.view];
GLint viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
Тогда я перевернуть ось х, потому что мое приложение находится в ландшафтном режиме и OPENGL Coords начать в другом углу, чем окно координаты
tapLoc.x = viewport[2] - tapLoc.x;
и выполнить unprojection с GLKitMathUnproject при г = 0 и г = 1 значения, а затем передать полученные векторы в функцию, которая будет возвращать координаты ячейки пользователя повернутой в качестве структуры BPPoint (всего два целых чисел , x и y) , В настоящее время на карте нет преобразований, поэтому я предполагаю, что я должен использовать идентификационную матрицу для ее преобразования, а матрица проекции была сделана с помощью glkmatrix4makeperspective.
GLKVector3 nearPt = GLKMathUnproject(GLKVector3Make(tapLoc.x, tapLoc.y, 0.0), GLKMatrix4Identity, [BPGlobalEnv globalVars].cameraMatrix, &viewport[0] , &testResult);
GLKVector3 farPt = GLKMathUnproject(GLKVector3Make(tapLoc.x, tapLoc.y, 1.0), GLKMatrix4Identity, [BPGlobalEnv globalVars].cameraMatrix, &viewport[0] , &testResult);
BPPoint destination = [gameEngine.currMap gridForPoint: farPt fromPoint: nearPt];
Это тело этого метода. Я в основном просто зацикливаюсь и перегенерирую геометрию для вершины каждого квадрата моей карты (неэффективно, я знаю) тем же методом, который я использовал, чтобы получить геометрию, чтобы перейти в VBO, чтобы нарисовать ее в первую очередь.
-(BPPoint) gridForPoint: (GLKVector3) ray fromPoint: (GLKVector3) cameraCoords
{
size_t i = 0;
size_t j;
GLfloat* buffer = malloc(sizeof(GLfloat) * squareSize);
for (NSArray* row in self.mapCells) {
j = 0;
for (BPGridCell* cell in row) {
GLfloat a[3];
a[0] = i * tileSize;
a[1] = cell.height * step;
a[2] = j * tileSize;
GLfloat b[3];
b[0] = (i + 1) * tileSize;
b[1] = cell.height * step;
b[2] = (j + 1) * tileSize;
[self squareForPoint:a point:b pointer: buffer];
GLKVector3 v1 = GLKVector3Make(buffer[0], buffer[1], buffer[2]);
GLKVector3 v2 = GLKVector3Make(buffer[3], buffer[4], buffer[5]);
GLKVector3 v3 = GLKVector3Make(buffer[6], buffer[7], buffer[8]);
GLKVector3 v21 = GLKVector3Make(buffer[9], buffer[10], buffer[11]);
GLKVector3 v22 = GLKVector3Make(buffer[12], buffer[13], buffer[14]);
GLKVector3 v23 = GLKVector3Make(buffer[15], buffer[16], buffer[17]);
if ([self ray: ray fromCamera: cameraCoords intersectsTriangleWithV1: v1 V2: v2 V3: v3] ||
[self ray: ray fromCamera: cameraCoords intersectsTriangleWithV1: v21 V2: v22 V3: v23]) {
NSLog(@"found intersection");
free(buffer);
BPPoint toReturn;
toReturn.x = i;
toReturn.y = j;
NSLog(@"%ld, %ld", i, j);
return toReturn;
}
j += 1;
}
i += 1;
}
free(buffer);
BPPoint toReturn;
toReturn.x = i;
toReturn.y = j;
NSLog(@"%ld, %ld", i, j);
return toReturn;
}
И код для тестирования треугольника для пересечения, который я преобразовал в ObjC отсюда (http://www.cs.virginia.edu/~gfx/Courses/2003/ImageSynthesis/papers/Acceleration/Fast%20MinimumStorage%20RayTriangle%20Intersection.pdf) следующим образом:
-(BOOL) ray: (GLKVector3) ray fromCamera: (GLKVector3) camera intersectsTriangleWithV1: (GLKVector3) v1 V2: (GLKVector3) v2 V3: (GLKVector3) v3
{
GLKVector3 e1 = GLKVector3Subtract(v2, v1);
GLKVector3 e2 = GLKVector3Subtract(v3, v1);
GLKVector3 h = GLKVector3CrossProduct(ray, e2);
float det = GLKVector3DotProduct(e1, h);
if (det > -0.00001 && det < 0.00001) {
return NO;
}
float invDet = 1.0/det;
GLKVector3 s = GLKVector3Subtract(camera, v1);
float u = GLKVector3DotProduct(s, h) * invDet;
if (u < 0.0 || u > 1.0) {
return NO;
}
GLKVector3 q = GLKVector3CrossProduct(s, e1);
float v = invDet * GLKVector3DotProduct(ray, q);
if (v < 0.0 || u + v > 1.0) {
return NO;
}
return YES;
}
Когда я запускаю это с картой 10х10, он печатает 10,10 для координат, не обнаруживая пересечения, как правило. Где я заблуждался концептуально или в реализации этого или обоих?