// // // Camera Constrained xform tool // // Jeremy Pronk 2004 // // jeremy@thereisnoluck.com // www.thereisnoluck.com // // What does it do? // ---------------- // // This script is a transform tool for constraining the transform or scale of an object to the selected cameras // perspective line. It was created to assist in building geometry from photos (photogrammetry based modelling). // // // How to Use // ---------- // // Once this script has been sourced you can invoke the tool using "setToolTo camConstrainTransTool". // You can source the script on start up by adding source "jpCamConstrainTools.mel" to your userSetup.mel file // // Once the tool is invoked you will notice the "dolly" mouse cursor in the viewport. Dragging in a viewport will // translate all selected objects (and components) along the objects perspective line FOR THE ACTIVE CAMERA. If you // wish to use another camera, select it before selecting your transformable objects, it will be used and the // active camera will be ignored. Dragging vertically will transform at twice the rate of dragging horizontally. // // Holding down CTRL will scale the object (from the active camera) rather than transform. // // // (PLEASE CONTACT ME IF YOU PLAN TO MODIFY THIS SCRIPT FOR RE-DISTRIBUTION) // // KNOWN ISSUES: // * scale transform does not undo correctly global string $cCTToolCamera; global string $cCTToolObjs[]; global vector $cCTToolObjsStartTranslate[]; global vector $cCTToolObjsStartScale[]; global float $cCTToolLastDragPos[2]; global float $cCTToolScaleSpeedX = 1000.0; global float $cCTToolScaleSpeedY = 500.0; global float $cCTToolSpeedX = 100.0; global float $cCTToolSpeedY = 50.0; proc vector worldPos( string $obj ) { float $worldPf[] = `xform -q -ws -t $obj`; return << $worldPf[0], $worldPf[1], $worldPf[2] >>; } global proc float[] pointMatrixMultForMe ( float $p[], float $m[] ) { float $pp[3]; $pp[0] = (( $m[0] * $p[0] ) + ( $m[4] * $p[1] ) + ( $m[8] * $p[2] ) + $m[12]); $pp[1] = (( $m[1] * $p[0] ) + ( $m[5] * $p[1] ) + ( $m[9] * $p[2] ) + $m[13]); $pp[2] = (( $m[2] * $p[0] ) + ( $m[6] * $p[1] ) + ( $m[10] * $p[2] ) + $m[14]); return $pp; } global proc float[] objToWorld ( float $p[], string $obj ) { float $wm[16] = `getAttr ($obj + ".worldMatrix")`; return ( pointMatrixMultForMe ( $p, $wm ) ); } global proc float[] worldToObj ( float $p[], string $obj ) { float $wm[16] = `getAttr ($obj + ".worldInverseMatrix")`; return ( pointMatrixMultForMe ( $p, $wm ) ); } proc vector camConstrainTranslate( string $cam, string $obj, float $depthInc ) { /*string $attrs[] = `listAttr -st depth $obj`; if ( $attrs[0] != "relativeDepth" ) { addAttr -longName "relativeDepth" -at "float" $obj -dv 1.0; } $relativeDepthOffset*/ vector $worldP = worldPos( $obj ); float $worldPfloat[]; $worldPfloat[0] = $worldP.x; $worldPfloat[1] = $worldP.y; $worldPfloat[2] = $worldP.z; float $camP[] = worldToObj( $worldPfloat, $cam ); float $newCamP[3]; $newCamP[2] = $camP[2] + $depthInc; $newCamP[0] = $camP[0] * $newCamP[2] / $camP[2]; $newCamP[1] = $camP[1] * $newCamP[2] / $camP[2]; float $newWorldP[] = objToWorld( $newCamP, $cam ); return << $newWorldP[0], $newWorldP[1], $newWorldP[2] >>; } global proc installCamConstrainTransTool() { print "Camera Constrain Tools v0.1\n"; print "by Jeremy Pronk\n"; print "www.thereisnoluck.com\n\n"; draggerContext -pressCommand "camConstrainTransToolPress" -dragCommand "camConstrainTransToolDrag" -releaseCommand "camConstrainTransToolRelease" -cursor "dolly" camConstrainTransTool; } global proc camConstrainTransToolPress() { global string $cCTToolCamera; global float $cCTToolLastDragPos[2]; global string $cCTToolObjs[]; global vector $cCTToolObjsStartTranslate[]; global vector $cCTToolObjsStartScale[]; string $selected[] = `ls -sl`; // // first find the camera we are using to constrain our transform $cCTToolCamera = ""; string $camType[] = `ls -showType $selected[0]`; if ( $camType[1] == "transform" ) { string $camChild[] = `listRelatives -c -type "camera" $camType[0]`; if ( size( $camChild ) ) { $cCTToolCamera = $camChild[0]; } } else if ( $camType[1] == "camera" ) { $cCTToolCamera = $camType[0]; } // // check a camera has been selected and get the list of objs to be transformed if ( $cCTToolCamera == "" ) // { $cCTToolCamera = getCurrentCameraShape(); $cCTToolObjs = $selected; } else { // first element was the camera, so remove it string $camToRemove[] = { $selected[0] }; $cCTToolObjs = stringArrayRemove( $camToRemove, $selected ); } // // save the initial transform information int $objCount=0; for ( $obj in $cCTToolObjs ) { $cCTToolObjsStartTranslate[$objCount] = worldPos( $obj ); float $sScale[] = `xform -q -r -s $obj`; $cCTToolObjsStartScale[$objCount] = << $sScale[0], $sScale[1], $sScale[2] >>; $objCount++; } // // float $pressPosition[] = `draggerContext -query -anchorPoint camConstrainTransTool`; $cCTToolLastDragPos[0] = $pressPosition[0]; $cCTToolLastDragPos[1] = $pressPosition[1]; /*print ( "Using " + $cCTToolCamera + "...\n" ); print ( "Transforming " ); print $cCTToolObjs;*/ // switch off undo while dragging undoInfo -stateWithoutFlush off; } global proc camConstrainTransToolDrag() { global string $cCTToolCamera; global string $cCTToolObjs[]; global float $cCTToolLastDragPos[2]; global float $cCTToolSpeedX; global float $cCTToolSpeedY; global float $cCTToolScaleSpeedX; global float $cCTToolScaleSpeedY; if ( size( $cCTToolObjs ) ) { float $dragPosition[] = `draggerContext -query -dragPoint camConstrainTransTool`; //int $button = `draggerContext -query -button camConstrainTransTool`; string $modifier = `draggerContext -query -modifier camConstrainTransTool`; float $dragChangeX = $dragPosition[0] - $cCTToolLastDragPos[0]; float $dragChangeY = $dragPosition[1] - $cCTToolLastDragPos[1]; if ( $modifier == "none" ) { float $depthChangeSmall = $dragChangeX / $cCTToolSpeedX; float $depthChangeLarge = $dragChangeY / $cCTToolSpeedY; float $depthChange = $depthChangeSmall + $depthChangeLarge; int $objCount=0; for ( $obj in $cCTToolObjs ) { vector $newWP = camConstrainTranslate( $cCTToolCamera, $obj, $depthChange ); move -a -ws ($newWP.x) ($newWP.y) ($newWP.z) $obj; $objCount++; } } else if ( $modifier == "ctrl" ) { float $scaleChangeSmall = $dragChangeX / $cCTToolScaleSpeedX; float $scaleChangeLarge = $dragChangeY / $cCTToolScaleSpeedY; float $scaleChange = $scaleChangeSmall + $scaleChangeLarge; // // camera constrained scale works (simply) by scaling the obj(s) with the pivot // at the camera.... int $objCount=0; for ( $obj in $cCTToolObjs ) { float $camWP[16] = `getAttr ( $cCTToolCamera+".worldMatrix")`; scale -p ($camWP[12]) ($camWP[13]) ($camWP[14]) -r (1.0+$scaleChange) (1.0+$scaleChange) (1.0+$scaleChange) $obj; $objCount++; } } $cCTToolLastDragPos[0] = $dragPosition[0]; $cCTToolLastDragPos[1] = $dragPosition[1]; refresh; } } global proc camConstrainTransToolRelease() { global string $cCTToolCamera; global string $cCTToolObjs[]; global vector $cCTToolObjsStartTranslate[]; global vector $cCTToolObjsStartScale[]; vector $newObjWorldPos[]; vector $newObjCamScale[]; // save new transform, and then transform back to original int $objCount=0; for ( $obj in $cCTToolObjs ) { $newObjWorldPos[$objCount] = worldPos( $obj ); vector $orgWP = $cCTToolObjsStartTranslate[$objCount]; move -a -ws ($orgWP.x) ($orgWP.y) ($orgWP.z) $obj; /*$newObjCamScale[$objCount] = floatToVector( `xform -q -r -s $obj` ); vector $camWP = worldPos( $cCTToolCamera ); vector $orgScale = $cCTToolObjsStartScale[$objCount]; scale -p ($camWP.x) ($camWP.y) ($camWP.z) -r ($orgScale.x) ($orgScale.y) ($orgScale.z) $obj;*/ $objCount++; } // turn undo on undoInfo -stateWithoutFlush on; // now "re-apply" the transform for UNDO $objCount=0; for ( $obj in $cCTToolObjs ) { vector $newWP = $newObjWorldPos[$objCount]; move -a -ws ($newWP.x) ($newWP.y) ($newWP.z) $obj; $objCount++; } } global proc string getCurrentCameraShape() { string $currentCamera; string $panel = `getPanel -wf`; if ( "modelPanel" == `getPanel -to $panel` ) { $currentCamera = `modelEditor -q -camera $panel`; } // have we returned the camera shape or transform node? string $camType[] = `ls -st $currentCamera`; if ( $camType[1] != "camera" ) { // don't have the shape node, so find it! string $camShape[] = `listRelatives -c -f -typ camera $currentCamera`; $currentCamera = $camShape[0]; } return $currentCamera; } if ( `contextInfo -ex camConstrainTransTool` ) deleteUI -tc camConstrainTransTool; installCamConstrainTransTool(); //setToolTo camConstrainTransTool;