macroScript viewFrustrum category:"MB Tools" ( -- for 3ds max R6 - (c) 2004 by M. Breidt (martin@breidt.net) -- Script based on the cameraCone.ms script by Christopher Subiago (csubagio@hotmail.com, http://www.3dluvr.com/subagio/scripts.html) -- -- Invoke this macroScript with a camera selected to create a geometric representation of the -- camera's view frustrum. Useful in combination with Vol.Select for selecting only visible geometry. -- Frustrum depth can be modified interactively; Angle offset allows for creating a frustrum with -- an offset from the camera's FOV (to include extra geometry at the edge of the frustrum, for example). -- Note: The script is robust to renaming the camera or frustrum object. -- -- Known limitation: Does not update immediately when image aspect was changed in render settings -- or when angle offset is changed; just move the timeslider once to get a proper update -- on isEnabled do ((superClassOf selection[1])==camera) on execute do ( camObj = selection[1] if superClassOf camObj == camera then ( -- create view frustrum geometry camPyr = Pyramid widthsegs:1 depthSegs:1 heightsegs:1 width:100 depth:100 height:100 camPyr.transform = camObj.transform camPyr.wirecolor = color 0 255 0 camPyr.renderable = false -- add xform modifier xmod = xform name:"viewFrustrum" addmodifier camPyr xmod xmod.gizmo.position = [0,0, -camPyr.baseobject.height] camPyr.name = ( camObj.name as string + " cone" ) camPyr.parent = camObj -- create custom attribute holder = attributes "cone" ( parameters main rollout:params ( coneDepth type:#float ui:spn1 default:100 angleOffset type:#float ui:spn2 default:0 ) rollout params "Cone Depth" ( spinner spn1 "Cone Depth:" pos:[15,6] width:141 height:16 range:[0,1e+010,0] scale:5 spinner spn2 "Angle Offset:" pos:[15,25] width:141 height:16 range:[-180,180,0] ) ) -- attach CA to xform modifier custattributes.add xmod holder #unique -- wire CA params to cone params for depth paramWire.connect xmod.cone[#coneDepth] camPyr.baseobject[#height] "coneDepth" paramWire.connect xmod.cone[#coneDepth] xmod.gizmo[#position] "[0,0,-coneDepth]" -- create script controllers for frustrum width and depth wc = camPyr.baseObject.width.controller = float_script() dc = camPyr.baseObject.depth.controller = float_script() -- create Custom Attribute that will store the camera node and attach it the script controllers camCA = attributes "nodeStore" ( parameters main ( camNode type:#node ) ) custAttributes.add wc camCA #unique custAttributes.add dc camCA #unique -- store camera node in CAs wc.nodeStore.camNode = dc.nodeStore.camNode = camObj -- create script controllers for adjusting cone width and height camStr = "this.nodeStore.camNode" -- special treatment needed to retrieve frustrum node since this cannot be stored in CA (circular dependency) headStr = "dependsOn " + camStr + "\n if isValidNode " + camStr + " then ( \npyrNode = (for ref in (refs.dependents this) where isValidNode ref collect ref)[1]\n" pyrStr = "pyrNode" fovStr = "tan ((" + camStr + ".fov + " + pyrStr + ".viewFrustrum.cone[#angleOffset].value)/2.0)" camPyr.width.controller.script=(headStr + "2 * "+pyrStr+".height * " + fovStr + "\n) else 100") camPyr.depth.controller.script=(headStr + "2 * "+pyrStr+".height * " + fovStr + " * renderHeight / (renderWidth*renderPixelAspect)\n) else 100") select camPyr ) -- end: if superclassof ) -- end: on execute do )