【问题标题】:Where did I go wrong trying to implement picking with raycasting in OpenGL ES 2.0 for iOS?尝试在 iOS 的 OpenGL ES 2.0 中使用光线投射实现拾取时我哪里出错了?
【发布时间】:2013-06-28 00:43:23
【问题描述】:

我正在尝试为 iPad 应用程序在 OpenGL ES 2.0 中使用光线投射实现拾取。具体来说,我想知道用户点击了由高度不同的方形单元组成的类似我的世界地图的哪个单元。但是,我的代码没有找到与任何单元格的交集。

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

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 以首先绘制它的方法相同。

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

我从这里 (http://www.cs.virginia.edu/~gfx/Courses/2003/ImageSynthesis/papers/Acceleration/Fast%20MinimumStorage%20RayTriangle%20Intersection.pdf) 转换为 objc 的用于测试相交三角形的代码如下:

-(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 而不会找到交叉点。我在哪里搞砸了概念或实施这个或两者兼而有之?

【问题讨论】:

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


    【解决方案1】:

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

    【讨论】:

      猜你喜欢
      • 2012-12-20
      • 1970-01-01
      • 1970-01-01
      • 2016-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-10
      • 1970-01-01
      相关资源
      最近更新 更多