2012-12-19 58 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

好吧,世界空間點並不是在正確的地方繪製的,我在我的問題中添加了一些代碼,你能發現任何在我的計算中看起來完全錯誤的東西嗎? –