2012-12-19 61 views
2

我正在使用OpenGL ES 2.0和最新的iOS。屏幕空间raycasting

我有一个3D模型,我希望用户能够通过点击屏幕来选择模型的不同部分。我发现this教程将像素空间屏幕坐标转换为世界空间射线,并已实施射线AABB相交测试以确定模型的相交部分。

我得到一些命中模型上看似随机的部分模型。所以我需要调试这个功能,但我真的不知道从哪里开始。

我不能确切地得出代表射线(因为它是走出来就会出现一个点的相机)的线,这样我就可以看到一对夫妇的调试这个办法:

  1. 检查模型部分的边界框。那么有没有一种简单的方法用OGL ES画出一个给定最小和最大点的边界框?

  2. 沿着光线的路径绘制一些3D物体。这似乎更复杂。

  3. 实际调试raycast和交叉码。这似乎是最难完成的算法,因为算法是众所周知的(我把我的实时碰撞检测书中的交叉点测试直接进行了)。

如果任何人都可以帮忙,或者想要我发表一些代码,我可以真正使用它。

这里是我的代码转换为世界空间:

- (IBAction)tappedBody:(UITapGestureRecognizer *)sender 
{ 
    if (!editMode) 
    { 
     return; 
    } 
    CGPoint tapPoint = [sender locationOfTouch:0 inView:self.view]; 
    const float tanFOV = tanf(GLKMathDegreesToRadians(65.0f*0.5f)); 
    const float width = self.view.frame.size.width, 
       height = self.view.frame.size.height, 
       aspect = width/height, 
       w_2 = width * 0.5, 
       h_2 = height * 0.5; 

    CGPoint screenPoint; 
    screenPoint.x = tanFOV * (tapPoint.x/w_2 - 1)/aspect; 
    screenPoint.y = tanFOV * (1.0 - tapPoint.y/h_2); 

    GLKVector3 nearPoint = GLKVector3Make(screenPoint.x * NEAR_PLANE, screenPoint.y * NEAR_PLANE, NEAR_PLANE); 
    GLKVector3 farPoint = GLKVector3Make(screenPoint.x * FAR_PLANE, screenPoint.y * FAR_PLANE, FAR_PLANE); 

    GLKVector3 nearWorldPoint = GLKMatrix4MultiplyVector3(_invViewMatrix, nearPoint); 
    GLKVector3 farWorldPoint = GLKMatrix4MultiplyVector3(_invViewMatrix, farPoint); 

    GLKVector3 worldRay = GLKVector3Subtract(farWorldPoint, nearWorldPoint); 
    NSLog(@"Model matrix: %@", NSStringFromGLKMatrix4(_modelMatrix)); 
    worldRay = GLKVector4Normalize(worldRay); 

    [male intersectWithRay:worldRay fromStartPoint:nearWorldPoint]; 

    for (int i =0; i < 3; ++i) 
    { 
     touchPoint[i] = nearWorldPoint.v[i]; 
    } 
} 

这里就是我如何得到矩阵:

- (void)update 
{ 
// _rotation = 0; 

    float aspect = fabsf(self.view.bounds.size.width/self.view.bounds.size.height); 
    GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, NEAR_PLANE, FAR_PLANE); 

    self.effect.transform.projectionMatrix = projectionMatrix; 
    GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -5.0f); 

    // Compute the model view matrix for the object rendered with ES2 
    _viewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 0.0f); 
    _modelMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); 
    _modelViewMatrix = GLKMatrix4Rotate(_viewMatrix, _rotation, 0.0f, 1.0f, 0.0f); 
    _modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, _modelViewMatrix); 

    _invViewMatrix = GLKMatrix4Invert(_viewMatrix, NULL); 
    _invMVMatrix = GLKMatrix4Invert(_modelViewMatrix, NULL); 

    _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(_modelViewMatrix), NULL); 

    _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, _modelViewMatrix); 

    male.modelTransform = _modelMatrix; 

    if (!editMode) 
    { 
     _rotation += self.timeSinceLastUpdate * 0.5f; 
    } 
} 

回答

0

我不知道为什么这个固定的我有,但改变

screenPoint.x = tanFOV * (tapPoint.x/w_2 - 1)/aspect; 

screenPoint.x = tanFOV * (tapPoint.x/w_2 - 1) * aspect; 

GLKVector4 nearPoint = GLKVector4Make(screenPoint.x * NEAR_PLANE, screenPoint.y * NEAR_PLANE, NEAR_PLANE, 1); 
GLKVector4 farPoint = GLKVector4Make(screenPoint.x * FAR_PLANE, screenPoint.y * FAR_PLANE, FAR_PLANE, 1); 

GLKVector4 nearPoint = GLKVector4Make(screenPoint.x * NEAR_PLANE, screenPoint.y * NEAR_PLANE, -NEAR_PLANE, 1); 
GLKVector4 farPoint = GLKVector4Make(screenPoint.x * FAR_PLANE, screenPoint.y * FAR_PLANE, -FAR_PLANE, 1); 
问题

似乎已经修复了光线投射问题。仍然不确定为什么我的视图矩阵似乎表明摄像机正在向下看正Z轴,但是我的对象沿着z轴被翻译为负值

0

我不能确切地得出代表射线线(因为它是来自相机之外的 它将显示为一个点)

不要马上丢弃这个东西。难道你试图测试什么?我的意思是,如果你对事物没有正确的评价,那将是如此。但是,如果你有一个错误,它不会。

我会先用这个...如果你看到一个点刚好在你的手指下,转换是正确的,你可以开始调查你指出的其他选项,这些更复杂。

+0

在我计算的世界空间坐标处绘制它? –

+0

是的。如果需要,您还可以绘制屏幕空间点。它也应该与“线路点”一起在您的指尖下。如果可行,这意味着你的转换代码是完全正确的......几乎“按照定义”。 –

+0

好吧,世界空间点并不是在正确的地方绘制的,我在我的问题中添加了一些代码,你能发现任何在我的计算中看起来完全错误的东西吗? –