Last active
November 14, 2019 09:56
-
-
Save tokejepsen/48989dfeb031a8c9a67a2ea2e8a73e2c to your computer and use it in GitHub Desktop.
Maya Frustum Cutter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Select the camera you want to cut from, then the geometry you want | |
to be cut. | |
""" | |
import maya.cmds as cmds | |
import pymel.core as pm | |
def cut_to_frustum(camera, geometry): | |
# Gather relevant camera attributes. | |
focalLength = cmds.getAttr(camera + ".focalLength") | |
horizontalAperture = cmds.getAttr(camera + ".cameraAperture")[0][0] | |
nearClipping = cmds.getAttr(camera + ".nearClipPlane") | |
farClipping = cmds.getAttr(camera + ".farClipPlane") | |
# Calculate ratios. | |
plane = horizontalAperture * 25.4 | |
nearScaleValue = nearClipping * plane / focalLength | |
# Build geometry. | |
cube_transform, cube_shape = cmds.polyCube( | |
w=1, | |
h=1, | |
d=farClipping-nearClipping, | |
sy=1, | |
sx=1, | |
sz=1, | |
ax=[0, 1, 0], | |
ch=1, | |
name=camera.replace("Shape", "Frustrum") | |
) | |
cmds.setAttr( | |
cube_transform + ".translateZ", | |
nearClipping + (farClipping-nearClipping) * 0.5 | |
) | |
cmds.makeIdentity(apply=True, t=1, r=1, s=1, n=0, pn=1) | |
cmds.setAttr(cube_transform + ".rotatePivotZ", 0) | |
cmds.setAttr(cube_transform + ".scalePivotZ", 0) | |
cmds.setAttr(cube_transform + ".rotateY", 180) | |
# Use expressions to update frustum geo as FOV and apertures are changed. | |
scaleX = ( | |
"{}.scaleZ*{}.farClipPlane*{}.horizontalFilmAperture*25.4*0.94" | |
"/{}.focalLength".format(cube_transform, camera, camera, camera) | |
) | |
scaleY = ( | |
"{}.scaleZ*{}.farClipPlane*{}.verticalFilmAperture*25.4" | |
"/{}.focalLength".format(cube_transform, camera, camera, camera) | |
) | |
cmds.move(0, 0, 0, cube_transform + ".f[2]", absolute=True) | |
cmds.scale(nearScaleValue, 0, 1, cube_transform + ".f[2]", pivot=[0, 0, 0]) | |
cmds.expression( | |
s="{}.scaleX = {};{}.scaleY = {};".format( | |
cube_transform, scaleX, cube_transform, scaleY | |
), | |
n="{}_Expr".format(cube_transform) | |
) | |
cmds.parent(cube_transform, camera.getTransform().name(), relative=True) | |
cmds.parent(cube_transform, world=True) | |
# Difference operation. | |
pm.polyCBoolOp( | |
cube_transform, | |
geometry, | |
operation=2, | |
constructionHistory=False, | |
preserveColor=0, | |
classification=1, | |
name=geometry.name() | |
) | |
with pm.UndoChunk(): | |
selection = pm.ls(selection=True) | |
cut_to_frustum(selection[0].getShape(), selection[1]) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment