9 Replies Latest reply on Nov 20, 2009 8:57 AM by Paul@Creation

    Blender to After Effects exporter

      Hello!

      I'm working with a couple of people on a script that allow the exporting of camera data from Blender to After Effects, here ---> http://blenderartists.org/forum/showthread.php?t=70432 the discussion about it. By the way we have some problems about how to convert blender camera rotation data (which are global) to After Effects (which use local) (if it is not clear what I mean take a look at this post http://blenderartists.org/forum/showpost.php?p=879140&postcount=84 ). If someone know the WAY we will appreciate much :)

      Thank you in advance
        • 1. Re: Blender to After Effects exporter
          David Wigforss-Hv1BNN Level 2
          I couldn't correctly use it, but there's an exporter for Softimage XSI.  Perhaps it will help you.  It generates a .xml file.  For all of the associated files, you'll need to download @ www.mindthink.de - you need to register (free).<br /><br />Here's AE_export.js:<br /><br />// ===============================================================<br />// AE Export version 3.0<br />// This version of the exporter generates XML files.<br />// 08.08.2005 Helge Mathee<br />// in behalf of Electric-Umbrella GmbH<br />// -------------------------------------<br /><br />var text = '';<br />var tabs = 0;<br />var useTriangles = false;<br />aeExport2(useTriangles);<br /><br />function aeExport2(useTriangles){<br />     text = '';<br />     tabs = 0;<br />     <br />     if(!selection.count){<br />          logmessage('Nothing selected',siError);<br />          return false;<br />     }<br />     <br />     var cameras = new ActiveXObject('XSI.Collection');<br />     var lights = new ActiveXObject('XSI.Collection');<br />     var nulls = new ActiveXObject('XSI.Collection');<br /><br />     var passes = ActiveProject.ActiveScene.Passes;<br />     if(passes.count<1){<br />          logmessage('Fatal error. No Passes present.',siError);<br />     }<br />     <br />     var frameIn = GetValue('PlayControl.In');<br />     var frameOut = GetValue('PlayControl.Out');<br />     var fps = GetValue("PlayControl.Rate");<br />     <br />     log('<root framein='+frameIn+' frameout='+frameOut+' fps='+fps+'>');<br />     tabs++;<br /><br />     var helper = ActiveSceneRoot.AddNull();<br />     for(var i=0;i<selection.count;i++){<br />          var progress = XSIUIToolkit.ProgressBar;<br />          progress.caption = 'exporting '+selection(0)+' ...';<br />     <br />          if(selection(i).type=='camera'){<br />               log('<camera name='+selection(i).name+'>');<br />               tabs++;<br />               var cons = selection(i).kinematics.constraints.filter('dircns');<br />               var constr = false;<br />               if(cons){<br />                    for(var j=0;j<cons.count;j++){<br />                         if(cons(j).constraining(0).type=='CameraInterest'){<br />                              cons = cons(j);<br />                              constr = cons.constraining(0).kinematics.global;<br />                              break;<br />                         }<br />                    }<br />               }else{<br />                    cons = null;<br />               }<br />               <br />               progress.maximum = frameOut-frameIn;<br />               progress.visible = true;<br />          <br />               for(var frame=frameIn;frame<=frameOut;frame++){<br />                    if(cons){<br />                         log('<key'+x3d(selection(i),frame)+' fov='+round(selection(i).ActivePrimitive.Parameters('fov').value(frame))+' roll='+round(cons.parameters('roll').value(frame))+' interest='+round(constr.parameters('posx').value(frame))+'|'+round(constr.parameters('pos y').value(frame))+'|'+round(constr.parameters('posz').value(frame))+'>');<br />                    }else{<br />                         log('<key'+x3d(selection(i),frame)+' fov='+round(selection(i).ActivePrimitive.Parameters('fov').value(frame))+'>');<br />                    }<br />                    progress.increment();<br />               }<br />               progress.visible = false;<br />               tabs--;<br />               log('</camera>');<br />          }else if(selection(i).type=='light'){<br />               log('<light name='+selection(i).name+' type='+selection(i).ActivePrimitive.parameters('type').value+'>');<br />               tabs++;<br /><br />               progress.maximum = frameOut-frameIn;<br />               progress.visible = true;<br />          <br />               var shader = selection(i).ActivePrimitive.Parameters('LightShader').source;<br />               for(var frame=frameIn;frame<=frameOut;frame++){<br />                    log('<key'+x3d(selection(i),frame)+' color='+shader.parameters('color').parameters('red').value(frame)+'|'+shader.parameters(' color').parameters('green').value(frame)+'|'+shader.parameters('color').parameters('blue') .value(frame)+' intensity='+shader.parameters('intensity').value(frame)+'>');<br />                    progress.increment();<br />               }<br />               progress.visible = false;<br />          <br />               tabs--;<br />               log('</light>');<br />          }else if(selection(i).type=='polymsh'){<br /><br />               var primitive = selection(i).activePrimitive;<br />               if(useTriangles)<br />                    var facetCount = primitive.geometry.triangles.count;<br />               else<br />                    var facetCount = primitive.geometry.facets.count;<br />               var hasDeformation = primitive.constructionhistory.filter('',siOperatorFamily).count>4;;<br /><br />               var UVs = false;<br />               for(var j=0;j<primitive.geometry.clusters.count;j++){<br />                    var cls = primitive.geometry.clusters(j);<br />                    for(var k=0;k<cls.properties.count;k++){<br />                              if(cls.properties(k).type=='uvspace'){<br />                              UVs = cls.properties(k);<br />                              break;<br />                         }<br />                    }<br />                    <br />                    if(UVs)<br />                         break;<br />               }<br />               <br />               progress.maximum = facetCount;<br />               progress.visible = true;<br />               var thisFrameOut = (hasDeformation?frameOut:frameIn);<br />          <br />               for(var j=0;j<facetCount;j++){<br />                    log('<solid name='+selection(i).name+'_poly'+j+'>');<br />                    tabs++;<br />                    <br />                    for(var frame=frameIn;frame<=thisFrameOut;frame++){<br />                         if(useTriangles)<br />                              var facet = primitive.geometry(frame).triangles(j);<br />                         else<br />                              var facet = primitive.geometry(frame).facets(j);<br /><br />                         var points = facet.points;<br />                         var center = XSIMath.CreateVector3();<br />                         var kine = selection(i).kinematics.global.transform(frame);<br />                         <br />                         for(var k=0;k<points.count;k++)<br />                              center.AddInPlace(points(k).position);<br />                         center.ScaleInPlace(1/points.count);<br />                         <br />                         var x = XSIMath.CreateVector3();<br />                         var y = XSIMath.CreateVector3();<br />                         var z = XSIMath.CreateVector3();<br />                         var pos = XSIMath.CreateVector3();<br />                         var transform = XSIMath.CreateTransform();<br />                         var rotation = XSIMath.CreateRotation();<br />                         var matrix = XSIMath.CreateMatrix3();<br />                         <br />                         x.Sub(points(0).position,points(1).position);<br />                         y.Sub(points(2).position,points(1).position);<br />                         z.Cross(y,x);<br />                         y.Cross(z,x     );<br />                         x.NormalizeInPlace();<br />                         y.NormalizeInPlace();<br />                         z.NormalizeInPlace();<br />                         <br />                         matrix.Set(x.x,x.y,x.z,y.x,y.y,y.z,z.x,z.y,z.z);<br />                         rotation.SetFromMatrix3(matrix);<br />                         transform.SetRotation(rotation);<br />                         transform.SetTranslation(center);<br />                         helper.kinematics.local.parameters('rotorder').value = 0;<br />                         helper.kinematics.local.transform = transform;<br />                         helper.kinematics.local.parameters('rotorder').value = 5;<br /><br />                         var totalMax = 0;                         <br />                         for(var k=0;k<points.count;k++){<br />                              pos = XSIMath.MapWorldPositionToObjectSpace(transform,points(k).position);<br />                              if(Math.abs(pos.x)>totalMax)<br />                                   totalMax = Math.abs(pos.x);<br />                              if(Math.abs(pos.y)>totalMax)<br />                                   totalMax = Math.abs(pos.y);<br />                         }<br />                         var s = "";<br />                         for(var k=0;k<points.count;k++){<br />                              pos = XSIMath.MapWorldPositionToObjectSpace(transform,points(k).position);<br />                              s += ' pnt='+round(pos.x/totalMax)+"|"+round(pos.y/totalMax);<br />                         }<br />                         var angles = XSIMath.CreateVector3();<br />                         center = XSIMath.MapObjectPositionToWorldSpace(kine,center);<br />                         angles.x = helper.kinematics.local.parameters('rotx').value;<br />                         angles.y = helper.kinematics.local.parameters('roty').value;<br />                         angles.z = helper.kinematics.local.parameters('rotz').value;<br />                         log('<key frame='+frame+' size='+round(totalMax)+' pos='+round(center.x,5)+'|'+round(center.y)+'|'+round(center.z)+' ori='+round(angles.x,5)+'|'+round(angles.y)+'|'+round(angles.z)+s+">");<br />                         <br />                    }<br />                    <br />                    tabs--;<br />                    log('</solid>');<br />                    progress.increment();<br />               }<br />               progress.visible = false;<br /><br />          }else{<br />               log('<null name='+selection(i).name+'>');<br />               tabs++;<br /><br />               progress.maximum = frameOut-frameIn;<br />               progress.visible = true;<br />          <br />               for(var frame=frameIn;frame<=frameOut;frame++){<br />                    log('<key'+x3d(selection(i),frame)+'>');<br />                    progress.increment();<br />               }<br />               progress.visible = false;<br />          <br />               tabs--;<br />               log('</null>');<br />          }<br />     }<br /><br />     tabs--;<br />     log('</root>');<br />     DeleteObj(helper);<br /><br />     <br />     var fileBrowser = XSIUIToolkit.FileBrowser;<br />     fileBrowser.Filter = "XML (*.xml)|*.xml||";<br />     fileBrowser.ShowSave();<br />     var fileName = fileBrowser.filepathname;<br />     if(!fileName)<br />          return false;<br /><br />     var fso = new ActiveXObject('Scripting.FileSystemObject');<br />     var file = fso.CreateTextFile(fileName);<br />     file.write(text);<br />     file.close();<br />}<br /><br />function log(s){<br />     var t = '';<br />     for(var i=0;i<tabs;i++)<br />          t+='\t';<br />     if(!s)<br />          text += t+'\n';<br />     else<br />          text += t+s+'\n';<br />}
          • 2. Re: Blender to After Effects exporter
            David Wigforss-Hv1BNN Level 2
            Woops - too long... Here's the end.

            function x3d(obj,frame){
            var kineState = obj.kinematics.global;
            var s = ' frame='+frame;
            if(obj.type=='camera'){
            s+=' pos='+round(kineState.parameters('posx').value(frame))+'|'+round(kineState.parameters('po sy').value(frame))+'|'+round(kineState.parameters('posz').value(frame));
            }else{
            s+=' pos='+round(kineState.parameters('posx').value(frame))+'|'+round(kineState.parameters('po sy').value(frame))+'|'+round(kineState.parameters('posz').value(frame));
            s+=' rot='+round(kineState.parameters('rotx').value(frame))+'|'+round(kineState.parameters('ro ty').value(frame))+'|'+round(kineState.parameters('rotz').value(frame));
            s+=' scl='+round(kineState.parameters('sclx').value(frame))+'|'+round(kineState.parameters('sc ly').value(frame))+'|'+round(kineState.parameters('sclz').value(frame));
            }
            return s;
            }

            function round(x){
            return Math.floor(x*1000)/1000;
            }
            • 3. Re: Blender to After Effects exporter
              bartekskorupa Level 1

              Hi,

               

              I have just completed the exporter based on the script originally created by Thomas Volkmann aka knekke.

              Below you will find the link to the tutorial explaining in details how to use it:

               

              www.blender.bartekskorupa.com/-video/102.html

              • 4. Re: Blender to After Effects exporter
                Paul@Creation

                Bartek,

                 

                The very day I choose to look at blender camera exports is the day you post your very elegant updated script. Good timing!

                 

                In your tutorial video (very clear, by the way), you mention that the blender camera must be 'tracked to an empty'. I'm a complete novice to blender, and I would like to know how this is accomplished.

                 

                My particular situation is that I have imported 3d camera tracking data from voodoo and want to then export that camera move to AE. Would this involve locking an empty to the camera's existing movement? If so, how would I go about that?

                 

                Many thanks in advance,

                 

                Paul

                • 5. Re: Blender to After Effects exporter
                  bartekskorupa Level 1

                  Hi,

                  I am really glad that I could help someone.
                  The solution to your case would be as follows:
                  In blender:
                  (Follow the steps exactly)
                  1. Run the script created by Voodoo.
                  2. Hit SPACE --> Add --> Empty.
                  3. The newly created Empty is selected. Hold SHIFT and right click the Voodoo Camera. You now have both the Empty and the camera selected. The order of selection is important. First the Empty, then the camera. If you do exactly as described - you'll have it done right.
                  4. Hit Ctl-C and chose Location. This will copy the camera's location, and paste it to the Empty. Now the Empty is at the same location as the camera.
                  5. Hit Ctl-C again and chose Rotation. This will copy the rotation of the camera and paste it to the Empty. Now the camera and the empty have the same location and rotation.
                  6. Hit Ctl-P and confirm that you want to make Parent. The Empty has become the child of the camera.
                  7. Hit A to disselect all the objects.
                  8. Select the Empty with the right mouse button.
                  9. Hit alt-SPACE and chose "Local" as an orientation.
                  10. Grab the blue arrow (Empty's local Z axis and move it some distance away from the camera.
                  Now it's time to run my script.
                  Just select the camera, the newly created empty and some mesh if you have one. If you don't, I suggest you add some, to have a refference in After Effects.
                  In fact it is not necessary for the camera to be tracked to the empty, but you have to have an empty to become a POI in AE.
                  If you follow the instruction above - you will have the Empty that will be at the right position.
                  This solution is not yet tested by me, but I'm 99% sure it'll work.
                  If you still face some problems, I would gladly help you. You could just send me the script created by Voodoo. I can send you the proper blend file in return.
                  You will find my email on my website.
                  PS.
                  Remember to set the proper dimensions of your blender scene. If your footage uses non-square pixels, I can't guarantee it'll work. In that case I'd suggest you recalculate the dimensions of the composition using square pixels so that your footage fits into it.
                  • 6. Re: Blender to After Effects exporter
                    bartekskorupa Level 1

                    OK, even better. I just modified the script, so that you don't have to track your camera to an empty.

                    In blender:

                     

                    Select your Voodoo camera and go to the editing menu (F9). In the tab: "Link and materials" there are two fields. One called: CA: .....

                    and the other one called: OB:...

                    In the tab CA:..., change the name from whatever it says (Probably something like "Camera.001") to "Camera"

                     

                    Select your Voodoo camera, shift-select some mesh (You have to select the mesh. Otherwise you'll get en error), and run the script.

                    I attached the script to this message.

                    • 7. Re: Blender to After Effects exporter
                      Paul@Creation Level 1

                      Bartek,

                       

                      Thank you for such a detailed response, really very helpful. I tried your script again and performed everything exactly as you suggested, and it... sort-of worked! Copying camera attributes to the empty seemed to create a problem. I followed everything as you suggested, but copying position and rotation shunted the empty under the 'ground' plane, way off from the camera. The parenting command worked fine. Does the cursor need to be zeroed on the camera when generating the empty perhaps? Is it possible that the xyz axes have been inverted or flipped in the scene somehow?

                       

                      I went ahead and ran the script to see what would come out the other end, but it gave me an error in the console, something along the lines of 'can't find the camera "voodoo_camera"', which seems odd. There's only one camera and it's a simple scene.

                       

                      I'll try to attach both the .blend file in the state I left it and the original voodoo python file to this message so that you can see what I've tried to do. If you do have a moment to have a look at this at some point, I'd appreciate it very much. I'm just testing the workflow waters at the moment.

                       

                      Your script DOES work, it must be something I'm doing or not doing in my ignorance.

                       

                      Thanks,

                       

                      Paul

                      • 8. Re: Blender to After Effects exporter
                        bartekskorupa Level 1

                        OK, try this:

                         

                        First of all download the script I attached to my previous message.

                         

                         

                        - Open blender.

                         

                        - Erase everything in your scene

                         

                        - hit F10 and change the dimensions of your scene to match the tracked footage

                         

                        - Run the script created by Voodoo

                         

                        - Select your Voodoo camera and hit F9

                         

                        - In the panel "Link and material" change the name in both fields: OB:... and CA:... so that they are the same. Let it be "Camera"

                        (This is what causes the error. Name of the camera object has to be the same as the camera datablock linked to it. I found this just this morning)

                         

                        - add some mesh to your scene and place it at some useful location.

                         

                        - Open my script (the one called: "00_Blender2AE_newCompNoPOI.py")

                         

                        - select the voodoo camera and your mesh or the "cloud" created by voodoo.

                         

                        - run the script.

                         

                        It should work. I tried it myself with one of my voodoo tracks.

                        • 9. Re: Blender to After Effects exporter
                          Paul@Creation Level 1

                          Mr S,

                           

                          Only just managed to have another look at this and... It works flawlessly!

                           

                          Thanks again for your invaluable help. Stroke of genius.

                           

                          Best regards,

                           

                          Paul