How to get camera pitch when using two-point perspective?



if I set a viewport to two-point perspective, I don’t find a way to get the pitch angle of the camera.

IsTwoPointPerspectiveProjection returns true
CameraUp always returns the z-unit vector
CameraDirection.Z returns zero
CameraLocation and CameraTarget have the same Z value

How can I determine if I’m looking up or down in the viewport?

Thanks a lot,
Simon Weinberger

(Pascal Golay) #2

Hi Simon - it looks like the camera frustum is skewed in 2 pt perspective (Use F6 to display the camera) - that is, the camera to target vector is not level but the view plane on the frustum stays vertical - hence the up-vector… you may be able to use the camera-to-target vector to get the information you need…?



I ran into the same issue where the TwoPointPerspecive gets tricky to work with since the reported values (real target locations, lens length) are not correct - or ‘as expected’.

Here is how you can reverse-engineer the ‘real Target’ location - not the one that is always level with camera as reported by Rhino. From there, you can use Camera-Target vector as @Pascal mentioned to determine if you look up/down and the angle. Here is how it’s done in RhinoScript:

Function RealViewTarget() 

	'returns camera target point - center of vport for all projection modes

	If Rhino.ViewProjection() <> 3 Then 'regular Parallel or Perspective projection
		RealViewTarget = Rhino.ViewTarget()
	Else 'Two Point Perspective projection
		Dim P,T,C
		P = Rhino.ViewCameraPlane(): P = Rhino.MovePlane(P, Rhino.ViewTarget()) 'view plane @ target
		C = Rhino.XformScreenToWorld(array(Rhino.ViewSize()(0) / 2, Rhino.ViewSize()(1) / 2)) 'center of vport point in 3D space
		T = Rhino.LinePlaneIntersection(array(Rhino.ViewCamera(), C), P)  
	RealViewTarget = T
	End If

End Function




Thanks a lot @Jarek

it works perfectly. My final C# code for RhinoCommon looks like this:

Point3d GetRealViewTarget(RhinoViewport viewport)
    if (!viewport.IsTwoPointPerspectiveProjection)
        return viewport.CameraTarget;

    var center = new Point2d(viewport.Size.Width / 2.0, viewport.Size.Height / 2.0);
    var centerRay = viewport.ClientToWorld(center);

    if (viewport.GetCameraFrame(out var plane))
        if (plane.Translate(viewport.CameraTarget - plane.Origin))
            if (Intersection.LinePlane(centerRay, plane, out var x))
                return centerRay.PointAt(x);

    throw new Exception();


glad it helped. The C# is way above my head but good to see the same logic as in basic RhinoScript did the job.