在OpenGL ES 2.0 for iOS中尝试使用光线投射实现拾取时,我在哪里出错了?

时间:2013-06-30 21:59:17

标签: ios opengl-es opengl-es-2.0 glkit ray-picking

我正在尝试使用OpenGL ES 2.0中的光线投射为iPad应用程序进行挑选。具体来说,我想知道哪个类似类似于魔兽世界的地图的单元格是由方形单元组成的,这些单元格具有用户所使用的不同高度。但是,我的代码找不到与任何单元格的交集。

在我的手势识别器方法中,我首先获得了点和视口尺寸

UITapGestureRecognizer* tapRecognizer = (UITapGestureRecognizer*) recognizer;
CGPoint tapLoc = [tapRecognizer locationInView: self.view];

GLint viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);

然后我翻转x轴,因为我的应用程序处于横向模式,而openGL坐标开始于与窗口坐标不同的角落

tapLoc.x = viewport[2] -  tapLoc.x;

使用GLKitMathUnproject对z = 0和z = 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中的相同方法来首先绘制它。 / p>

-(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;
}

当我使用10x10地图运行时,它会打印10,10的坐标,而不会找到通常的交点。我在哪里搞砸概念或实施这个或两个?

1 个答案:

答案 0 :(得分:0)

我找到了解决方案:glgetintegerv调用返回了翻转值,大概是因为设备处于横向模式。我还必须从远点减去近点以获得正确的射线方向向量。