A billboard option to the picture frame would be nice indeed.

In the meantime you can try this bit of python, it orients all selected surfaces to face the camera of the selected viewport with the option of full and constrained rotation.

```
from Rhino import Commands, DocObjects, Geometry, Input
import scriptcontext
def generate_frame(forward):
forward.Unitize() # could fail should really check
up = Geometry.Vector3d.ZAxis
if forward.IsParallelTo(up) != 0:
up = Geometry.Vector3d.YAxis
side = Geometry.Vector3d.CrossProduct(forward, up)
side.Unitize() # could fail should really check
up = Geometry.Vector3d.CrossProduct(side, forward)
return (forward, side, up)
def orient_unconstrained(surface, camera_pt):
u = (surface.Domain(0).T0 + surface.Domain(0).T1) / 2.0
v = (surface.Domain(1).T0 + surface.Domain(1).T1) / 2.0
srf_pt = surface.PointAt(u, v)
srf_fwd = surface.NormalAt(u, v)
srf_fwd, srf_side, srf_up = generate_frame(srf_fwd)
target_fwd = camera_pt - srf_pt
target_fwd, target_side, target_up = generate_frame(target_fwd)
trans = Geometry.Transform.Translation(-Geometry.Vector3d(srf_pt))
rot = Geometry.Transform.Rotation(srf_side, srf_up, srf_fwd, target_side, target_up, target_fwd)
inv_trans = Geometry.Transform.Translation(Geometry.Vector3d(srf_pt))
return inv_trans * rot * trans
def orient_constrained(surface, camera_pt):
u = (surface.Domain(0).T0 + surface.Domain(0).T1) / 2.0
v = (surface.Domain(1).T0 + surface.Domain(1).T1) / 2.0
srf_pt = surface.PointAt(u, v)
srf_fwd = surface.NormalAt(u, v)
srf_fwd.Z = 0
target_fwd = camera_pt - srf_pt
target_fwd.Z = 0
return Geometry.Transform.Rotation(srf_fwd, target_fwd, srf_pt)
def orient_to_camera():
result, obj_refs = Input.RhinoGet.GetMultipleObjects("Select objects", False, DocObjects.ObjectType.Surface)
if result != Commands.Result.Success:
return
result, constrained = Input.RhinoGet.GetBool("Constrain z-axis", True, "no", "yes", True)
if result != Commands.Result.Success:
return
result, view = Input.RhinoGet.GetView("Select view")
if result != Commands.Result.Success:
return
camera_pt = view.ActiveViewport.CameraLocation
for obj_ref in obj_refs:
surface = obj_ref.Surface()
if not surface:
continue
xform = None
if constrained:
xform = orient_constrained(surface, camera_pt)
else:
xform = orient_unconstrained(surface, camera_pt)
scriptcontext.doc.ActiveDoc.Objects.Transform(obj_ref, xform, True)
if( __name__ == '__main__' ):
orient_to_camera()
scriptcontext.doc.ActiveDoc.Views.Redraw()
```