I'd like to convert a 3d position into 2d screen position. I had a look at a similar question: Projecting a 3D point to a 2D screen coordinate , but I dont understand it completely. I thought in order to calculate the 2d position I would need the projection matrix, but I dont see how it is used, apart from converting a point into the location coordinate space. Besides, is cam.FieldOfView equal to farZ in OpenGL?
Could someone please help me complete this function. Are the parameters sufficient to calculate the 2d position? Pos is already a vector relative to the camera position.
Vector2* convert(Vector3& pos, Matrix4& projectionMatrix, int screenWidth, int screenHeight)
{
float ratio = screenWidth / screenHeight;
...
screenX = screenWidth * ( 1.0f - screenX);
screenY = screenHeight * ( 1.0f - screenY);
return new Vector2(screenX, screenY);
}
Seems to me it would be something like that:
Vector2 Convert(Vector3 pos, const Matrix& viewMatrix, const Matrix& projectionMatrix, int screenWidth, int screenHeight)
{
pos = Vector3::Transform(pos, viewMatrix);
pos = Vector3::Transform(pos, projectionMatrix);
pos.X = screenWidth*(pos.X + 1.0)/2.0;
pos.Y = screenHeight * (1.0 - ((pos.Y + 1.0) / 2.0));
return Vector2(pos.X, pos.Y);
}
What are we doing here is just passing the Vector though the two transformation matrices: the view, then the projection. After the projection you get a vector with Y and X between -1 and 1. We do the appropriate transformation to obtain real pixel coordinates and return a new Vector2. Note that the Z component of 'pos' also store the depth of the point, in the screen space, at the end of the function.
You need the 'view' matrix because it defines where the camera is located and rotated. The projection only defines the way the 3D space is 'flattened' on the 2D space.
A field of view is not the farZ. A projection matrix has some parameters, among them:
Besides the math problem, you may use directly the Vector2 instead of a heap allocation (returning a pointer). Vector2 is a light structure and pointers are very likely to cause headaches in this context (where are you going to delete it, and so on). Also note that I used 'const' references as we do not modify them, except the vector. For this one we want a local copy, this is why it is not a reference at all.
Previous code only work if you do not do any rotations (for eg. GL.Rotate(rotation_x, 1.0, 0.0, 0.0)
).
But if you do here is the code:
private Vector2 Convert(Vector3 pos, Matrix4 viewMatrix, Matrix4 projectionMatrix, int screenWidth, int screenHeight)
{
pos = Vector3.Transform(pos, viewMatrix);
pos = Vector3.Transform(pos, projectionMatrix);
pos.X /= pos.Z;
pos.Y /= pos.Z;
pos.X = (pos.X + 1) * screenWidth / 2;
pos.Y = (pos.Y + 1) * screenHeight / 2;
return new Vector2(pos.X, pos.Y);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With