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?

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

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();
}