Reputation: 525
For my current project it is necessary, that I compute the screen coordinates of a given point in the world space in Unity.
I used this tutorial to write a methode to do so.
After some debugging the x and y screen coordinate are correct, but my z coordinates looks wrong and I have some more questions:
static public Vector3 convertWorldToScreenCoordinates (Vector3 point, PhotoData photoData)
{
// get the camera
Camera camera = GameObject.Find (photoData.cameraName).camera;
/*
* 1 convert P_world to P_camera
*/
Vector4 pointInCameraCoodinates = convertWorldToCameraCoordinates (point, photoData);
/*
* 2 convert P_camera to P_clipped
*/
Vector4 pointInClipCoordinates = camera.projectionMatrix * pointInCameraCoodinates;
/*
* 3 convert P_clipped to P_ndc
* Normalized Device Coordinates
*/
Vector3 pointInNdc = pointInClipCoordinates / pointInClipCoordinates.w;
/*
* 4 convert P_ndc to P_screen
*/
Vector3 pointInScreenCoordinates;
pointInScreenCoordinates.x = camera.pixelWidth / 2.0f * (pointInNdc.x + 1);
pointInScreenCoordinates.y = camera.pixelHeight / 2.0f * (pointInNdc.y + 1);
pointInScreenCoordinates.z = ((camera.farClipPlane - camera.nearClipPlane) * pointInNdc.z + (camera.farClipPlane + camera.nearClipPlane)) / 2.0f;
// return screencoordinates
return pointInScreenCoordinates;
}
PhotoData is a class, that contains some information about the camera. The important part here is that I can access the camera.
static public Vector4 convertWorldToCameraCoordinates (Vector3 point, PhotoData photoData)
{
// translate the point by the negative camera-offset
//and convert to Vector4
Vector4 translatedPoint = point - photoData.cameraPosition;
// by default translatedPoint.w is 0
translatedPoint.w = 1.0f;
// create transformation matrix
Matrix4x4 transformationMatrix = Matrix4x4.identity;
transformationMatrix.SetRow (0, photoData.camRight);
transformationMatrix.SetRow (1, photoData.camUp);
transformationMatrix.SetRow (2, - photoData.camForward);
Vector4 transformedPoint = transformationMatrix * translatedPoint;
return transformedPoint;
}
First of all, the tutorial mentions, that after computing the ndc-values, "the range of values is now normalized from -1 to 1 in all 3 axes". This is not true in my case and I do not see what I am doing wrong.
My second question is, does pointInClipCoordinates.z < 0
mean the world point is "behind" my camera?
And the last question so far is why do I have to use - photoData.camForward
?
// edit: updated code + questions
Upvotes: 1
Views: 3400
Reputation: 4889
For editor scripts, use HandleUtility.WorldToGUIPoint (available since Unity3D 4.12) to convert a world space point to a 2D GUI position.
Upvotes: 1