Wednesday, July 26, 2017

directx - Why are points adjusted using the projection and inverse view matrix during picking?


I am working on my first 3D game, which contains several vehicles placed on a board. I want to implement mouse picking of the vehicles. I found this great tutorial and used its code. But I don't understand part of the math.


Early in the function (listed below), I convert the input mouse coordinates into the -1 to +1 range:


// Create picking ray from camera position and mouse click

void VehiclePicker::SetPickingRay(LONG mouseX, LONG mouseY) {
float pointX, pointY;

/* Conversion to -1 to +1 here: */
// Move the mouse cursor coordinates into the -1 to +1 range.
pointX = ((2.0f * static_cast(mouseX)) / static_cast(SCREEN_WIDTH)) - 1.0f;
pointY = (((2.0f * static_cast(mouseY)) / static_cast(SCREEN_HEIGHT)) - 1.0f) * -1.0f;

...


Next, I adjust the points using the projection matrix. Listed below:


    XMFLOAT4X4 prMtrx;
// Convert projectionMatrix from XMMATRIX into XMFLOAT4X4 in order to pick its members
XMStoreFloat4x4(&prMtrx, _d3d->GetProjectionMatrix());
pointX = pointX / prMtrx._11;
pointY = pointY / prMtrx._22;

I don't understand what is exactly done here. I understand that I should somehow transform the points using the inverted projection matrix into world space. But in the tutorial they are using non-inverted projection matrix and using only two elements from it for dividing the points. Why? In tutorial, they say they want "Adjust the points using the projection matrix to account for the aspect ratio of the viewport." Could somebody please explain it?


The same question is for the next part of the code. In tutorial they say "Calculate the direction of the picking ray in view space." Could you please also explain this one?


    // Get the inverse of the view matrix.

XMFLOAT4X4 invViewMtrx;
// Convert inverseViewMatrix from XMMATRIX into XMFLOAT4X4 in order to pick its members
XMStoreFloat4x4(&invViewMtrx, XMMatrixInverse(nullptr, _camera->GetViewMatrix()));
XMFLOAT3 dir;
dir.x = (pointX * invViewMtrx._11) + (pointY * invViewMtrx._21) + invViewMtrx._31;
dir.y = (pointX * invViewMtrx._12) + (pointY * invViewMtrx._22) + invViewMtrx._32;
dir.z = (pointX * invViewMtrx._13) + (pointY * invViewMtrx._23) + invViewMtrx._33;
_pickingRayDirection = XMLoadFloat3(&dir);

I understand that the goal is to invert the process of rendering 3D scene into 2D screen. But I don't understand the math used.



Here's the rest of the function, for context:


    // Get the origin of the picking ray which is the position of the camera.
_pickingRayOrigin = _camera->GetPosition();

// And finally I must normalize the final vector
_pickingRayDirection = XMVector3Normalize(_pickingRayDirection);
}


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...