我正在使用OpenGL ES 2.0和最新的iOS。屏幕空間raycasting
我有一個3D模型,我希望用戶能夠通過點擊屏幕來選擇模型的不同部分。我發現this教程將像素空間屏幕座標轉換爲世界空間射線,並已實施射線AABB相交測試以確定模型的相交部分。
我得到一些命中模型上看似隨機的部分模型。所以我需要調試這個功能,但我真的不知道從哪裏開始。
我不能確切地得出代表射線(因爲它是走出來就會出現一個點的相機)的線,這樣我就可以看到一對夫婦的調試這個辦法:
檢查模型部分的邊界框。那麼有沒有一種簡單的方法用OGL ES畫出一個給定最小和最大點的邊界框?
沿着光線的路徑繪製一些3D物體。這似乎更復雜。
實際調試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;
}
}
在我計算的世界空間座標處繪製它? –
是的。如果需要,您還可以繪製屏幕空間點。它也應該與「線路點」一起在您的指尖下。如果可行,這意味着你的轉換代碼是完全正確的......幾乎「按照定義」。 –
好吧,世界空間點並不是在正確的地方繪製的,我在我的問題中添加了一些代碼,你能發現任何在我的計算中看起來完全錯誤的東西嗎? –