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
