Copying the world_matrix of the source cam to local_matrix is fine when you're in Nuke, but I wanted to export this as one baked camera to the outside world. And for the chan exporter to work, I need TRS values (which is where my other post came from about a camera round trip via chan losing precision).
-Ean On Sat, Feb 26, 2011 at 7:06 PM, Ivan Busquets <[email protected]>wrote: > Someone with stronger math skills should probably confirm or refute this, > but I think the issue is not so much scaling, but the combo of rotation + > non-uniform scaling. > > Rotation + non-uniform scaling, when done in that order, are in fact > skewing the camera. But, as I said when I originally posted it, that > decomposition script doesn't handle skewing. > > To do that you would need to decompose the rotation and scale component of > the matrix into rotation, scale, and skew. > > For such a case, though, it's probably easier to just copy the world_matrix > of the source camera into the local_matrix of the dest camera. You'll loose > the ability to easily animate or change the translation, rotation, scaling, > etc curves, but it'll be a perfect match. > And if you do need to make tweaks to such a camera, isn't it easier to do > it while you still have all the separate transforms (Axis->Axis->Camera) > anyway? > > Cheers, > Ivan > > > On Fri, Feb 25, 2011 at 1:15 AM, Ean Carr <[email protected]> wrote: > >> You're right. Scaling the camera breaks it. Will take a look at that when >> I have a few min. Thanks Sebastian. >> >> >> On Thu, Feb 24, 2011 at 2:03 PM, Sebastian Elsner >> <[email protected]>wrote: >> >>> Hey Ean, >>> >>> I just tested the script. Seems to work for simple setups, but I had >>> problems with some of the more crazier ones (which I have actually seen in >>> Production): >>> >>> set cut_paste_input [stack 0] >>> version 6.1 v2 >>> push $cut_paste_input >>> Axis2 { >>> translate {{curve x1 0 x10 0 x20 0.8400000334} {curve x1 0 x10 >>> 1.909999967 x20 0.9399999976} {curve x1 0 x10 -0.9549999833 x20 >>> 0.7500000596}} >>> rotate {{curve x1 0 x10 39.95999908 x20 -7.99200058} {curve x1 0 x10 >>> -23.64299965 x20 84.58200836} {curve x1 0 x10 0 x20 0}} >>> scaling {{curve x1 1 x10 0.6} {curve x1 1 x10 1.1} {curve x1 1}} >>> name Axis2 >>> selected true >>> xpos -262 >>> ypos -181 >>> } >>> Axis2 { >>> translate {{curve x15 0 x30 3.160000086} {curve x15 0 x30 0} {curve x15 >>> 0 x30 0}} >>> rotate {{curve x15 0 x30 12.65400028} {curve x15 0 x30 56.61000443} >>> {curve x15 0 x30 0}} >>> scaling {{curve x15 1} {curve x15 1} {curve x15 1}} >>> name Axis1 >>> selected true >>> xpos -262 >>> ypos -115 >>> } >>> Camera2 { >>> translate {{curve x25 0.4099999964 x36 0.4099999964} {curve x25 0 x36 >>> 0.3899999857} {curve x25 0 x36 0}} >>> rotate {{curve x25 0 x36 -14.65200043} {curve x25 0 x36 17.31599998} >>> {curve x25 0 x36 0}} >>> scaling {{curve x25 1} {curve x25 1} {curve x25 1}} >>> name Camera1 >>> selected true >>> xpos -262 >>> ypos -49 >>> } >>> >>> Maybe you want to have a look at it. >>> >>> cheers >>> >>> Sebastian >>> >>> >>> On 02/24/2011 02:23 PM, Ean Carr wrote: >>> >>>> For anyone who's interested: I took Ivan's function and added support >>>> for animated Axis / Camera nodes (it was only concatenating a single >>>> frame). Cheers -E >>>> >>>> def consolidateAnimatedNodeTransforms(axisNode): >>>> # This is based on Ivan B's consolidateNodeTransforms(). >>>> # Added support for animated Axis/Camera nodes. Also, if it's >>>> # a Camera being concatenated, then projection settings get copied. >>>> # -Ean C 24/Feb/2011 >>>> >>>> m = nuke.math.Matrix4() >>>> >>>> n = nuke.createNode(axisNode.Class()) >>>> n['scaling'].setExpression('curve') >>>> n['rotate'].setExpression('curve') >>>> n['translate'].setExpression('curve') >>>> >>>> if axisNode.Class() == 'Camera2': >>>> # If this is a Camera node, copy over important Projection >>>> settings. >>>> camNode = axisNode >>>> >>>> # Get the current values >>>> focal_v = camNode['focal'].toScript() >>>> haperture_v = camNode['haperture'].toScript() >>>> vaperture_v = camNode['vaperture'].toScript() >>>> near_v = camNode['near'].toScript() >>>> far_v = camNode['far'].toScript() >>>> win_translate_v = camNode['win_translate'].toScript() >>>> win_scale_v = camNode['win_scale'].toScript() >>>> winroll_v = camNode['winroll'].toScript() >>>> focal_point_v = camNode['focal_point'].toScript() >>>> >>>> # Copy them over to new Camera >>>> n['focal'].fromScript(focal_v) >>>> n['haperture'].fromScript(haperture_v) >>>> n['vaperture'].fromScript(vaperture_v) >>>> n['near'].fromScript(near_v) >>>> n['far'].fromScript(far_v) >>>> n['win_translate'].fromScript(win_translate_v) >>>> n['win_scale'].fromScript(win_scale_v) >>>> n['winroll'].fromScript(winroll_v) >>>> n['focal_point'].fromScript(focal_point_v) >>>> >>>> first_frame_v = nuke.root()['first_frame'].value() >>>> last_frame_v = nuke.root()['last_frame'].value() >>>> >>>> scale_anim = n['scaling'].animations() >>>> rotate_anim = n['rotate'].animations() >>>> translate_anim = n['translate'].animations() >>>> >>>> for i in range(int(first_frame_v), int(last_frame_v+1)): >>>> >>>> k = axisNode['world_matrix'] >>>> k_time_aware = axisNode['world_matrix'].getValueAt(i) >>>> >>>> for y in range(k.height()): >>>> for x in range(k.width()): >>>> m[x+(y*k.width())] = k_time_aware[y + k.width()*x] >>>> >>>> transM =nuke.math.Matrix4(m) >>>> transM.translationOnly() >>>> rotM = nuke.math.Matrix4(m) >>>> rotM.rotationOnly() >>>> scaleM = nuke.math.Matrix4(m) >>>> scaleM.scaleOnly() >>>> >>>> scale = (scaleM.xAxis().x, scaleM.yAxis().y, >>>> scaleM.zAxis().z) >>>> >>>> rot = rotM.rotationsZXY() >>>> rotDegrees = ( math.degrees(rot[0]), math.degrees(rot[1]), >>>> math.degrees(rot[2]) ) >>>> >>>> trans = (transM[12], transM[13], transM[14]) >>>> >>>> for s in range(3): >>>> scale_anim[s].setKey(i, scale[s]) >>>> rotate_anim[s].setKey(i, rotDegrees[s]) >>>> translate_anim[s].setKey(i, trans[s]) >>>> >>>> >>>> >>>> On Mon, Nov 29, 2010 at 11:33 AM, Scott Willman <[email protected] >>>> <mailto:[email protected]>> wrote: >>>> >>>> Wow, Ivan, thank you! This should definately get me started :) >>>> >>>> Ivan Busquets wrote: >>>> >>>> What he said :) >>>> >>>> If you just want to use that within a gizmo/group, linking to >>>> the world_matrix of your input Axis/Camera should be enough to >>>> replicate all concatenated transforms. >>>> >>>> However, if you need to get back absolute values in terms of >>>> position/rotation/scale, you'll need to derive them yourself >>>> (with a little help from nuke.math) >>>> >>>> Here's an example if you just wanted to get the final >>>> concatenated position: >>>> >>>> ###################### >>>> import math >>>> >>>> def getAxisWPos(axisNode): >>>> >>>> k = axisNode['world_matrix'] >>>> m = nuke.math.Matrix4() >>>> >>>> for y in range(k.height()): >>>> for x in range(k.width()): >>>> m[x+(y*k.width())] = k.value(x,y) >>>> >>>> p = m.transform(nuke.math.Vector3(0,0,0)) >>>> return (p.x, p.y, p.z) >>>> >>>> worldPos = getAxisWPos(nuke.selectedNode()) >>>> ###################### >>>> >>>> Or, if you wanted to create a new Axis/Camera node and fill it >>>> with the concatenated translation, rotation and scale values, >>>> you could do something like this: (please note that this should >>>> account for everything except for skew transformations) >>>> >>>> ###################### >>>> def consolidateNodeTransforms(axisNode): >>>> >>>> k = axisNode['world_matrix'] >>>> m = nuke.math.Matrix4() >>>> >>>> nuke.selectAll() >>>> nuke.invertSelection() >>>> k = axisNode['world_matrix'] >>>> m = nuke.math.Matrix4() >>>> for y in range(k.height()): >>>> for x in range(k.width()): >>>> m[x+(y*k.width())] = k.value(x,y) >>>> >>>> transM =nuke.math.Matrix4(m) >>>> transM.translationOnly() >>>> rotM = nuke.math.Matrix4(m) >>>> rotM.rotationOnly() >>>> scaleM = nuke.math.Matrix4(m) >>>> scaleM.scaleOnly() >>>> scale = (scaleM.xAxis().x, scaleM.yAxis().y, >>>> scaleM.zAxis().z) >>>> rot = rotM.rotationsZXY() >>>> trans = (transM[12], transM[13], transM[14]) >>>> >>>> n = nuke.createNode(axisNode.Class()) >>>> n['scaling'].setValue(scale) >>>> n['rotate'].setValue((math.degrees(rot[0]), >>>> math.degrees(rot[1]), math.degrees(rot[2]))) >>>> n['translate'].setValue(trans) >>>> >>>> consolidateNodeTransforms(nuke.selectedNode()) >>>> ###################### >>>> >>>> >>>> Disclaimer: I just wrote those and have only done a couple of >>>> tests, so there's a good chance they may break (no exceptions >>>> handled, etc), but hopefully it'll get you on the right track. >>>> >>>> Hope that helps. >>>> >>>> Cheers, >>>> Ivan >>>> >>>> On Sun, Nov 28, 2010 at 3:20 PM, Frank Rueter >>>> <[email protected] <mailto:[email protected]> >>>> <mailto:[email protected] <mailto:[email protected]>>> >>>> >>>> wrote: >>>> >>>> that's what the world matrix knob is for (in 6.1) >>>> >>>> >>>> On Nov 29, 2010, at 12:12 PM, [email protected] >>>> <mailto:[email protected]> >>>> <mailto:[email protected] <mailto:[email protected]>> >>>> wrote: >>>> >>>> > I've got a camera that has an Axis node plugged in. The camera >>>> also has >>>> > transforms on it. Is there a way to get the resolved >>>> world-space >>>> > pos/rot/scale of the camera? >>>> > >>>> > Thanks guys >>>> > >>>> > >>>> > >>>> > >>>> > Cinesite (Europe) Ltd. Registered Office: HemelOne, Boundary >>>> Way, Hemel Hempstead, Herts, HP2 7YU Registered in Cardiff >>>> No. >>>> 2820389 VAT No. 630 5446 60 >>>> > _______________________________________________ >>>> > Nuke-python mailing list >>>> > [email protected] >>>> <mailto:[email protected]> >>>> <mailto:[email protected] >>>> <mailto:[email protected]>> >>>> >>>> > >>>> >>>> http://support.thefoundry.co.uk/cgi-bin/mailman/listinfo/nuke-python >>>> >>>> _______________________________________________ >>>> Nuke-python mailing list >>>> [email protected] >>>> <mailto:[email protected]> >>>> <mailto:[email protected] >>>> <mailto:[email protected]>> >>>> >>>> >>>> http://support.thefoundry.co.uk/cgi-bin/mailman/listinfo/nuke-python >>>> >>>> >>>> >>>> ------------------------------------------------------------------------ >>>> >>>> _______________________________________________ >>>> Nuke-python mailing list >>>> [email protected] >>>> <mailto:[email protected]> >>>> >>>> http://support.thefoundry.co.uk/cgi-bin/mailman/listinfo/nuke-python >>>> >>>> >>>> Cinesite (Europe) Ltd. Registered Office: HemelOne, Boundary Way, >>>> Hemel Hempstead, Herts, HP2 7YU Registered in Cardiff No. 2820389 >>>> VAT No. 630 5446 60 >>>> _______________________________________________ >>>> Nuke-python mailing list >>>> [email protected] >>>> <mailto:[email protected]> >>>> http://support.thefoundry.co.uk/cgi-bin/mailman/listinfo/nuke-python >>>> >>>> >>>> >>>> >>>> _______________________________________________ >>>> Nuke-python mailing list >>>> [email protected] >>>> http://support.thefoundry.co.uk/cgi-bin/mailman/listinfo/nuke-python >>>> >>> >>> -- >>> Sebastian Elsner - Pipeline TD - r i s e | fx >>> >>> t: +49 30 201 803 00 [email protected] >>> c: +49 175 336 5739 7548 www.risefx.com >>> >>> r i s e | fx GmbH >>> Schlesische Strasse 28, Aufgang B 10997 Berlin >>> Richard-Byrd-Strasse 12, 50829 Cologne >>> Geschaeftsfuehrer: Sven Pannicke, Robert Pinnow >>> Handelsregister Berlin HRB 106667 B >>> >>> _______________________________________________ >>> Nuke-python mailing list >>> [email protected] >>> http://support.thefoundry.co.uk/cgi-bin/mailman/listinfo/nuke-python >>> >> >> >> _______________________________________________ >> Nuke-python mailing list >> [email protected] >> http://support.thefoundry.co.uk/cgi-bin/mailman/listinfo/nuke-python >> >> > > _______________________________________________ > Nuke-python mailing list > [email protected] > http://support.thefoundry.co.uk/cgi-bin/mailman/listinfo/nuke-python > >
_______________________________________________ Nuke-python mailing list [email protected] http://support.thefoundry.co.uk/cgi-bin/mailman/listinfo/nuke-python
