Maya Frustum Visualizer


Why Maya doesn’t offer this functionality out of the box is a mystery to me. I suspect there is actually a way to do it but it’s so buried I can’t find it. I needed it for a recent job so I’m putting it out there for public consumption. Anyway, it’s simple: just select a camera and run the script to visualize the frustum. It should update if you change the camera transforms, film back and FOV. Use it, change it, break it, fix it, improve it at your leisure…

 """A Maya Python script that builds frustum geometry based on the selected camera. Thomas Hollier 2015.""" 
import maya.cmds as cmds
import math, sys

#--------- Gather relevant camera attributes
import maya.cmds as cmds
import math, sys

#--------- Gather relevant camera attributes
camera =

if not cmds.objectType(camera, isType="camera"):
	print "ERROR: You need to select a camera."

focalLength = cmds.getAttr(camera[0]+".focalLength")
horizontalAperture = cmds.getAttr(camera[0]+".cameraAperture")[0][0]
verticalAperture = cmds.getAttr(camera[0]+".cameraAperture")[0][1]
nearClipping = cmds.getAttr(camera[0]+".nearClipPlane")
farClipping = cmds.getAttr(camera[0]+".farClipPlane")

print "---- Camera Attributes:\n\tfocal length: %s\n\thorizontal aperture: %s" % (focalLength, horizontalAperture)

#--------- compute FOV just for kicks, and to verify numbers match
adjacent = focalLength
opposite = horizontalAperture*.5*25.4

print "---- Right Triangle Values:\n\tadjacent: %s\n\topposite: %s" % (adjacent, opposite)

horizontalFOV = math.degrees(math.atan(opposite/adjacent))*2

print "\tcomputed horizontal FOV: %s" % (horizontalFOV)

#--------- calculate ratios
plane = horizontalAperture*25.4
nearScaleValue = nearClipping*plane/focalLength
farScaleValue = farClipping*plane/focalLength

print "---- Lens:\n\tprojection ratio: %s" % (plane/focalLength)

#--------- build geometry
myCube = cmds.polyCube(w=1, h=1, d=farClipping-nearClipping, sy=1, sx=1, sz=1, ax=[0,1,0], ch=1, name=camera[0].replace("Shape", "Frustrum"))
cmds.setAttr(myCube[0]+".translateZ", nearClipping+(farClipping-nearClipping)*.5)
cmds.makeIdentity(apply=True, t=1, r=1, s=1, n=0, pn=1);
cmds.setAttr(myCube[0]+".rotatePivotZ", 0)
cmds.setAttr(myCube[0]+".scalePivotZ", 0)
cmds.setAttr(myCube[0]+".rotateY", 180)

#--------- use expressions to update frustum geo as FOV and apertures are changed 
scaleX = "%s.scaleZ*%s.farClipPlane*%s.horizontalFilmAperture*25.4/%s.focalLength" % (myCube[0],camera[0],camera[0],camera[0])
scaleY = "%s.scaleZ*%s.farClipPlane*%s.verticalFilmAperture*25.4/%s.focalLength" % (myCube[0],camera[0],camera[0],camera[0])

cmds.move(0,0,0, myCube[0]+".f[2]", absolute=True)
cmds.scale(nearScaleValue, 0, 1, myCube[0]+".f[2]", pivot=[0,0,0])
cmds.expression(s="%s.scaleX = %s;%s.scaleY = %s;" % (myCube[0],scaleX,myCube[0],scaleY), n="%s_Expr" % myCube[0])
cmds.parent(myCube, camera, relative=True)

Building an Ultra Large Format Camera, Part 1

Art, Atoms

The basic elements of a camera

One of the cool things about a camera is that at its core, it’s very simple. All you need is a lens that focuses light and a surface that this light gets focused on. The process of bending light with lenses to focus on a surface was first explored during the Renaissance with the camera obscura. It wasn’t until the 19th century that people figured out how to keep a record of how much light hit a particular area of that surface. Anyway, to make a camera, all you really need is a lens and a surface for the light to hit, and to create an image from a camera, you either need to trace the image you see projected on the surface or you need some kind of coating on the surface that reacts to light.


Is that a large lens in your pocket?

After giving me a taste of 4×5 tintypes, my buddy at Tintypebooth showed me some large old lenses from photographic systems used in spy planes that he had bought on ebay. These things are serious! They are very heavy and the glass is super thick; there is just something massive about them, and when you hold one and feel its weight, you can’t help but be awed by their image making potential and you get possessed by an urge to unlock that potential. He pitched the idea of building a ultra large format camera with one of them, a little “Kodak Aero-Ektar 24” 610mm” number, weighing in at just over 10 lbs and sporting a few scratches I like to think were caused by the strafing of some of the Luftwaffe’s last Messerschmitts.

Let’s decode those numbers, shall we? The 24” is the size of the image plane and 610mm (also 24”) is the focal length.Based on my previous post about lenses, it means that at its shortest, this camera will be a little over two feet long. At four feet of distance between the lens and the plane, the image on the focal plane will be the same size as the subject in focus four feet from the lens, and six feet will create an image bigger than reality. The film holder will need to accommodate plates that will be 24 inches on one side. I may need a bigger car…


I need a plan

Patience is a virtue I’ve always been in somewhat limited supply of. We have this killer lens… What’s the fastest and cheapest way we can get a picture out of it? Sure, we can design a fancy camera with a lot of bells and whistles but it would take a long time and cost a pretty penny. For now, I just need a bare bones proof of concept prototype. I’ll focus on the basic pieces and see if I can build it myself. I’ll build the back out of oak and do all the struts and supports using aluminum channels. The animated image above is a Maya model I built to scale that shows how all the pieces need to fit together. It doesn’t look too difficult, does it? One thing not shown in the animation is that the back that will hold the plate will be interchangeable with another back that will have the ground glass necessary to focus. The process will be as follows: first you will use the ground glass back to focus, slide it out, and then slide in the film back to load your camera.


Baby got back

Kim Kardashian’s got nothing on this bad boy! I built this 24″x20″ film back over the past couple weeks. I’m not a great builder and my Home Depot tools are a bit wobbly so I wouldn’t call it fine craftsmanship but it will hopefully do the trick. Oh, and did I forget to mention it’s not exactly square? Yeah… Let’s just say it’s square enough. It’s made from 1″x2″ and 1/4″x2″ red oak lumber which I routed to get the insets. It will make a great example when we eventually hire a finish carpenter for the next fancy version of the camera. Here are some pictures of the various pieces it’s made of (you can also see that I like to wear my slippers when I take pictures of my handy work).

More to come…

Here are the steps that come next and will be documented in a hopefully not too distant future.

  • I already bought the aluminum extrusions that are necessary to build the film back support, the lens plate holder, and the rails. I will need to learn how to properly drill in aluminum and figure out how to connect all the pieces. (anyone in Venice with a drill press?)
  • I will built the lens plate, mount the lens on the plate, and mount the plate on the rails.
  • Last will be creating the bellows. Not too sure how that will work but what the hell! We’ve got a few ideas. I’m sure we’ll figure something out.

See? It’s basically like it’s done already…

The three main attributes of a camera lens

Art, Electrons

If you ever want to embark on the foolish pursuit of building a camera, you will need to understand how lenses work. The three attribute that control the behavior of a basic camera lenses are focal length, format and aperture.

Focal length

The focal length is the distance from the lens at which infinite rays converge. For example, if you have a 50mm lens, infinity is in focus when the plane of the image is 50 millimeters away from the lens. A lens’s focal length is a factor of how much it bends the light. The more the bend, the closer to the lens the rays converge and the smaller the projected image. This, in turn, means that the focal length can also be used as an indication of the magnification of the image.


The format represents the intended size of the image plane that the lens is designed to project onto, such as 35mm or 4×5. The combination of the focal length and format determine the lens’s field of view. This is why a lens with the same focal length gives you a different amount of magnification on different formats. (illustration)


The aperture gives a measure in f-stops of how “fast” the lens is. It is often thought of as the size of the opening in the lens, but in photography, it actually is the ratio of the focal length over the diameter of the lens opening. This has the advantage of remaining proportionally equal across the different sizes of photographic systems. If you use the same f-stop in a tiny phone camera and a big SLR using the same ISO setting, the same shutter speed will expose both images similarly. As the size of the opening increases, more light gets in but the thinner the focal plane is.

Finding the focal plane

The last relevant piece of information is the formula that determines the distance of the focal plane to the lens for rays that are closer to the camera than infinity. The relationship between the distance of an object to the lens (S1), and the distance of the lens to the focal plane of that object(S2) is defined by this formula:
1/S1 + 1/S2 = 1/focal_length
Solving for S1, this becomes:
S1 = (S2 * focal_length)/(focal_length - S2)
If you plug in your own numbers, you will notice that the closer your object is to the lens, the farther away the focal plane will be from the lens.

Useful python functions

# Given a specific focal length and distance to subject, how close to the lens does the image plane converge?
def distanceOfFocusPlaneToLens(distanceToSubject, focalLength):
v= (focalLength*distanceToSubject)/(distanceToSubject-focalLength)
print ("when subject is at %s the focal plane is %s from the lens" % (distanceToSubject, v))

#FOV calculator
def FOVFromFocalAndAperture(focal, aperture):
    return math.degrees(2*math.atan(aperture/(focal * 2)))