Hi,
I’m trying to find a way to correctly calculate the world width and height of my screen in world units. To do that I need to calculate 2 corners and then calculate the distance in width and height.
I know about the Camera.main.ViewportToWorldPoint(Vector3(1,1,CameraDist));
BUT…I have a camera that looks down on the Y axis on a 3D plane AND it’s rotated slightly to give the plane below a perspective view.
First of all…if my camera position is (0, 10, 0) and looks down the Y axis should I use:
Camera.main.ViewportToWorldPoint(Vector3(1, CameraDist, 1)) for the top-right corner?
And second, how do I take in account the fact that the camera is a bit rotated? (it doesn’t look down straight to the Y axis).
If the camera isn’t perfectly perpendicular to the ground plane, the distances between the corners will be different! Any screen point (2D) corresponds in the 3D world to a line that passes through the point and the camera position. You must specify which point in this line you’re interested in. A common approach is to define a logical plane and use Plane.Raycast to get the distance from the camera. If you want to find the camera corners on an horizontal plane positioned at (0,0,0), for instance, you could use something like this:
// create logical plane perpendicular to Y and at (0,0,0):
var plane = new Plane(Vector3.up, Vector3(0,0,0));
var ray: Ray;
var distance: float;
ray = Camera.main.ViewportPointToRay(Vector3(0,0,0)); // bottom left ray
if (plane.Raycast(ray, distance)){
var botLeft: Vector3 = ray.GetPoint(distance);
}
ray = Camera.main.ViewportPointToRay(Vector3(0,1,0)); // top left ray
if (plane.Raycast(ray, distance)){
var topLeft: Vector3 = ray.GetPoint(distance);
}
ray = Camera.main.ViewportPointToRay(Vector3(0,1,0)); // top left ray
if (plane.Raycast(ray, distance)){
var topLeft: Vector3 = ray.GetPoint(distance);
}
ray = Camera.main.ViewportPointToRay(Vector3(1,0,0)); // bottom right ray
if (plane.Raycast(ray, distance)){
var botRight: Vector3 = ray.GetPoint(distance);
}
ray = Camera.main.ViewportPointToRay(Vector3(1,1,0)); // top right ray
if (plane.Raycast(ray, distance)){
var topRight: Vector3 = ray.GetPoint(distance);
}
You need to calculate 3 points: bottom-left, bottom-right, and top-right and then check the distances between them. Distance between b-l and b-r is the width and the distance between b-r and t-r is the height. I wrote a simple function to demonstrate.
function CalculateScreenSizeInWorldCoords () : Vector2 {
var cam = Camera.main;
var p1 = cam.ViewportToWorldPoint(Vector3(0,0,cam.nearClipPlane));
var p2 = cam.ViewportToWorldPoint(Vector3(1,0,cam.nearClipPlane));
var p3 = cam.ViewportToWorldPoint(Vector3(1,1,cam.nearClipPlane));
var width : float = (p2 - p1).magnitude;
var height : float = (p3 - p2).magnitude;
var dimensions : Vector2 = Vector2(width,height);
return dimensions;
}
Usage:
function Start () {
var dimensions : Vector2 = CalculateScreenSizeInWorldCoords();
Debug.Log("Width = " + dimensions.x + "; Height is = " + dimensions.y);
}