//SIZZLEX .comp Fusion 6 Composition @[ // (c)2005 Andersson Technologies LLC // Export the current camera and the objects hung from it. // // Note: Fusion doesn't like spaces in its node names, so we take out spaces // in camera names, tracker names, mesh names, etc // // Questions: // treatment of limited frame ranges, use of trimIn/Out? // // Updates in 2012 for Fusion 6 by Stefan Ihringer : // * Support for stereo camera pairs // * Removed workaround code for a point cloud bug in Fusion 5.0 // * Characters other than alphanumeric letters are invalid in node names and will be replaced by "_" // * Fixed cross-platform problems for object paths in FBXMesh // * Added project info to comp's comments tab and footage name to camera's comments // * Nodes aligned to grid and spaced for tile pictures // * Create locked cameras to prevent their accidental modifications // * Disabled clip lists in Loader, fixed length calculation and supported QuickTime // * Updated input names of 3D tools (SceneInput and Output instead of "Data3D") // * Generate meshes that are positioned correctly when imported into Fusion. axisMode = 1 // Y-Up-right rotOrder = 1 // XYZ bias = 0 // frame bias relObSize = 0.02 rel_tk_size = 0.01 use_flen = 0 relScnDist = 3.0 incl_prefs = 1 both = 1 // export both cameras? is_stereo = Scene.activeObj.cam.shot.stereoType if(1) dlg = NewDialog("fu6comp") dlg.Check("bias", "Start at Frame 1", bias) dlg.Float("relObSize", "Relative Object Size", 0.01, relObSize, 1) dlg.Float("rel_tk_size", "Relative Tracker Size", 0.001, rel_tk_size, 1) dlg.Float("relScnDist", "Relative screen distance", 0.1, relScnDist, 10) dlg.Check("use_flen", "Animate FL, not FOV", use_flen); if(is_stereo > 0) dlg.Check("both", "Export both stereo cams", both) end dlg.Check("incl_prefs", "Include prefs & comp comments", incl_prefs); dlg.Show() bias = dlg.bias relObSize = dlg.relObSize rel_tk_size = dlg.rel_tk_size relScnDist = dlg.relScnDist use_flen = dlg.use_flen incl_prefs = dlg.incl_prefs both = (is_stereo > 0 ? dlg.both : 0) end splurge = "" merge_cnt = 1 // Layout (initial coordinates chosen so they align with Fusion's grid) node_x0 = 110 node_y0 = 148.5 node_dx = 165 node_dy = 99 node_x = node_x0 node_y = node_y0 max_y = node_y0 node_cnt = 0 // square bracket messes up vim's syntax coloring chs = printf("%c\"", 91) che = "\"]" bquo = printf("%c", 91) equo = "]" DFComp() function Plunk() Enter("ViewInfo", "OperatorInfo") Define("Pos", "{ " node_x ", " node_y ", }") Exit() node_y += node_dy if (node_y > max_y) max_y = node_y // usually happens end end function KaChing() // Start the next line of nodes node_x += node_dx node_y = node_y0 node_cnt = 0 end function DFComp() // Locate a camera--the currently-active one maincam = Scene.activeObj.cam shot = maincam.shot startFrame = shot.start stopFrame = shot.stop nkey = stopFrame - startFrame + 1 indent = "" scenenm = "Scene" // Date/time stamp "\n-- Fusion 6 Exporter: " Scene.sourceFile "\n" DateTime("-- Exported %a, %b %d, %Y %I:%M:%S %p\n\n") // Here we go with a routine for each section. Enter("", "Composition") Define("CurrentTime", startFrame+bias) Define("RenderRange", "{ " startFrame+bias ", " stopFrame+bias ", }") Define("GlobalRange", "{ " startFrame+bias ", " stopFrame+bias ", }") Enter("Tools", "") ShotSetup(maincam) DoCamera(maincam, 0) for (objct in Obj) if (objct.cam == maincam && objct != maincam) DoObject(objct) end end for (lite in Lite) DoLight(lite) end if (#Lite == 0) ltnm = "DefaultLight" Wire2Merge3D(ltnm) Enter(ltnm, "LightPoint") Enter("Inputs", "") frame = startFrame lside = 0.05 * maincam.worldSize SetChan("Transform3DOp.Translate.X", maincam.x + lside*maincam.ax) SetChan("Transform3DOp.Translate.Y", maincam.y + lside*maincam.ay) SetChan("Transform3DOp.Translate.Z", maincam.z + lside*maincam.az) SetChan("Transform3DOp.Rotate.X", 0) SetChan("Transform3DOp.Rotate.Y", 0) SetChan("Transform3DOp.Rotate.Z", 0) Exit() Plunk() Exit() end // The non-parented meshes go here, parented ones with their objects. for (mesh in Mesh) if (typeof(mesh.obj) == "Double") DoMesh(mesh) end end for (xtra in Extra) DoExtra(xtra) end // add second Loader and connect second Camera3D for stereo shots? if(is_stereo && both) othercam = (is_stereo == 1 ? shot.right.cam : shot.left.cam) shot = othercam.shot // place other camera above all nodes that have been created so far node_x = node_x0 node_y = node_y0 - node_dy ShotSetup(othercam) node_y = node_y0 - node_dy DoCamera(othercam, 1) end Merge() Exit() if (incl_prefs) Prefs() // Set overall flow properties. end Exit() end // Merge all the 3D nodes into one master node, add a render node function Merge() node_x += node_dx node_y = (node_y0 + max_y) / 2 - node_dy/2 tmp_y = node_y clean_nm = NM(maincam.nm) Enter(clean_nm "Scene", "Merge3D") Enter("Inputs", "") splurge Exit() Plunk() Exit() node_x += node_dx node_y = tmp_y Enter(clean_nm "Renderer", "Renderer3D") Enter("Inputs", "") DefineInput("GlobalIn", startframe+bias) DefineInput("GlobalOut", stopframe+bias) DefineInput("Width", shot.width) DefineInput("Height", shot.height) DefineInput("PixelAspect", "{" shot.pixasp ", 1, }") SetSource("SceneInput", clean_nm "Scene", "Output") DefineInput("[\"RendererSoftware.LightingEnabled\"]", 1); Exit() Plunk() Exit() end function Wire2Merge3D(ndnm) lind = "\t\t\t\t" splurge = ( splurge lind "SceneInput" merge_cnt " = Input {\n" lind "\tSourceOp = \"" ndnm "\",\n" lind "\tSource = \"Output\",\n" lind "},\n" ) merge_cnt += 1 end // Only one level required. function PushMerge() splurge_save = splurge merge_cnt_save = merge_cnt splurge = "" merge_cnt = 1 end function PopMerge() splurge = splurge_save merge_cnt = merge_cnt_save end //--------------------------------------------------------------------- // Set up the shot---image on background function ShotSetup(ob) Enter(NM(ob.nm) "Shot", "Loader") Enter("Clips", "") Enter("", "Clip") if (shot.imageName == "") String("Filename", fix_slashes(shot.nm)) // don't write FormatID. Fusion will auto-detect both AVI and QuickTime files just fine. //String("FormatID", "AVIFormat") Define("StartFrame", 0) Define("Length", shot.length) Define("Multiframe", "true") Define("Saving", "false") Define("LengthSetManually", "false") Define("TrimIn", startFrame+bias) Define("TrimOut", stopFrame+bias) Define("ExtendFirst", 0) Define("ExtendLast", 0) Define("Loop", 1) Define("Reverse", "false") Define("ImportMode", 0) Define("PullOffset", 0) Define("Depth", 0) Define("TimeCode", 0) String("KeyCode", "") else String("Filename", fix_slashes(shot.imageName)) // this would only be correct if the sequence started at frame 0: //Define("Length", shot.length) Define("Length", stopFrame-startFrame+1) // prevents insane values from appearing in Loader if clip can't be found: Define("TrimIn", 0) Define("TrimOut", stopFrame-startFrame) Define("ExtendFirst", 0) Define("ExtendLast", 0) end Define("GlobalStart", startFrame+bias) Define("GlobalEnd", stopFrame+bias) Define("AspectMode", 2) Exit() Exit() Enter("Inputs","") DefineInput("EnableClipList", 0) DefineInput("CustomPixelAspect", "{ " shot.pixasp ", 1 }") Exit() Plunk() node_x += node_dx node_y = node_y0 Exit() end // Doesn't seem to be needed anymore function Prefs() Enter("Prefs", "") Enter("Comp", "") // put project info into comments tab (taken from Nuke exporter) Enter("Info", "") String("Comments", "Source: " Scene.sourceFile "\\r\\n" DateTime("Created: %a, %b %d, %Y %I:%M:%S %p")) Exit() Enter("FrameFormat","") String("Name","Custom") Define("Width", shot.width) Define("Height", shot.height) Define("Rate", shot.rate) Define("AspectX", shot.pixasp) Define("AspectY", 1) Define("GuideRatio", shot.aspect) // Define("TimeCodeType", 1) Exit() Enter("Unsorted","") Define("GlobalStart", startFrame+bias) Define("GlobalEnd", stopFrame+bias) Exit() Exit() Exit() end //--------------------------------------------------------------------- // Handle cameras function DoCamera(ob, second_eye) camnm = NM(ob.nm) frame = startFrame obsz = ob.worldSize * relObSize // for stereo export: wire only left stereo cam if(both == 0 || (is_stereo && ob.nm == shot.left.cam.nm)) Wire2Merge3D(camnm) end dtc = DoesTransformChange(ob) stationary = ( dtc & 1 ? 0 : 1) fixated = ( dtc & 2 ? 0 : 1) fixed_lens = IsLensFixed(ob) frame = startFrame Enter(camnm, "Camera3D") Define("Locked", "true") Enter("Inputs", "") if (stationary) SetChan("Transform3DOp.Translate.X", ob.x) SetChan("Transform3DOp.Translate.Y", ob.y) SetChan("Transform3DOp.Translate.Z", ob.z) else AnimChan("Transform3DOp.Translate.X", camnm "XOffset") AnimChan("Transform3DOp.Translate.Y", camnm "YOffset") AnimChan("Transform3DOp.Translate.Z", camnm "ZOffset") end if (fixated) SetChan("Transform3DOp.Rotate.X", ob.rx) SetChan("Transform3DOp.Rotate.Y", ob.ry) SetChan("Transform3DOp.Rotate.Z", ob.rz) else AnimChan("Transform3DOp.Rotate.X", camnm "XRotation") AnimChan("Transform3DOp.Rotate.Y", camnm "YRotation") AnimChan("Transform3DOp.Rotate.Z", camnm "ZRotation") end // TODO: skip PerspNearClip for now // TODO: skip PerspFarClip for now if (use_flen) if (fixed_lens) DefineInput("FLength", printf("%lf", ob.fl)) else Enter("FLength", "Input") String("SourceOp", camnm "FL") String("Source", "Value") Exit() end else DefineInput("FLength", printf("%lf", ob.fl)) // NEEDED! DefineInput("AovType", 1) // horizontal FOV mode if (fixed_lens) DefineInput("AoV", printf("%lf", ob.fov)) else Enter("AoV", "Input") String("SourceOp", camnm "FOV") String("Source", "Value") Exit() end end DefineInput("ApertureW", shot.backPlateWidth/25.4) DefineInput("ApertureH", shot.backPlateWidth / shot.aspect/25.4) DefineInput("IDepth", ob.worldSize * relScnDist) DefineInput("PerspFarClip", ob.worldSize * (relScnDist+1)) DefineInput("FilmGate", "FuID { \"User\", }") DefineInput("[\"SurfacePlaneInputs.Lighting\"]", 1) DefineInput("[\"SurfacePlaneInputs.IsAffectedByLights\"]", 0) SetSource("ImageInput", camnm "Shot", "Output") // For stereo: if this is the left camera, add a connection to the right one if(is_stereo && both && ob.nm == shot.left.cam.nm) SetSource("[\"Stereo.RightCamera\"]", NM(shot.right.cam.nm), "Output") end // Get the basename of the shot name. PC or Mac, w/w-o path, w/w-o .extn // (based on Nuke exporter) shotName = shot.nm cnt = fmax( rindex(shotName, "\\"), rindex(shotName, "/") ) shotName = substr(shotName, cnt+1) cnt = rindex(shotName, ".") shotName = substr(shotName, 1, cnt-1) DefineInput("Comments", "\"" shotName "\"") Exit() Plunk() Exit() if (!stationary) DoChannel(ob, "XOffset", "x", 0, 1, 1) DoChannel(ob, "YOffset", "y", 1, 0, 1) DoChannel(ob, "ZOffset", "z", 1, 0.706, 0) end if (!fixated) DoChannel(ob, "XRotation", "rx", 0, 1, 0.706) DoChannel(ob, "YRotation", "ry", 0.706, 0, 1) DoChannel(ob, "ZRotation", "rz", 0.706, 1, 0) end if (!fixed_lens) if (use_flen) DoChannel(ob, "FL", "fl", 0, 1, 0) else DoChannel(ob, "FOV", "fov", 0, 1, 0) end end // meshes and point cloud for first stereo camera only if(second_eye == 0) for (mesh in Mesh) if (typeof(mesh.obj) != "Double" && mesh.obj == ob) DoMesh(mesh) end end PointCloud(ob) FarPointCloud(ob) end end // Handle objects function DoObject(ob) enter_obj_x = node_x enter_obj_y = node_y node_x -= node_dx PushMerge() objectnm = NM(ob.nm) frame = startFrame obsz = ob.worldSize * relObSize dtc = DoesTransformChange(ob) stationary_obj = ( dtc & 1 ? 0 : 1) fixated_obj = ( dtc & 2 ? 0 : 1) frame = startFrame Wire2Merge3D(objectnm "Base") Enter(objectnm "Base", "Locator3D") // Enter(objectnm "Base", "Shape3D") // Enter("Inputs", "") // DefineInput("Shape", "FuID { \"SurfaceSphereInputs\", }") // SetChan("SurfaceSphereInputs.Radius", relObSize * ob.worldSize) // Exit() Plunk() Exit() // Meshes here for (mesh in Mesh) if (typeof(mesh.obj) != "Double" && mesh.obj == ob) DoMesh(mesh) end end PointCloud(ob) exit_obj_y = node_y node_x = enter_obj_x node_y = (enter_obj_y + exit_obj_y) / 2 - node_dy/2 Enter(objectnm, "Merge3D") Enter("Inputs", "") if (stationary_obj) SetChan("Transform3DOp.Translate.X", ob.x) SetChan("Transform3DOp.Translate.Y", ob.y) SetChan("Transform3DOp.Translate.Z", ob.z) else AnimChan("Transform3DOp.Translate.X", objectnm "XOffset") AnimChan("Transform3DOp.Translate.Y", objectnm "YOffset") AnimChan("Transform3DOp.Translate.Z", objectnm "ZOffset") end if (fixated_obj) SetChan("Transform3DOp.Rotate.X", ob.rx) SetChan("Transform3DOp.Rotate.Y", ob.ry) SetChan("Transform3DOp.Rotate.Z", ob.rz) else AnimChan("Transform3DOp.Rotate.X", objectnm "XRotation") AnimChan("Transform3DOp.Rotate.Y", objectnm "YRotation") AnimChan("Transform3DOp.Rotate.Z", objectnm "ZRotation") end splurge Exit() Plunk() Exit() PopMerge() Wire2Merge3D(objectnm) if (!stationary_obj) DoChannel(ob, "XOffset", "x", 0, 1, 1) DoChannel(ob, "YOffset", "y", 1, 0, 1) DoChannel(ob, "ZOffset", "z", 1, 0.706, 0) end if (!fixated_obj) DoChannel(ob, "XRotation", "rx", 0, 1, 0.706) DoChannel(ob, "YRotation", "ry", 0.706, 0, 1) DoChannel(ob, "ZRotation", "rz", 0.706, 1, 0) end node_y = exit_obj_y // these are on the normal level // Normal trackers go in the pointcloud, but independent ones are here // as individual locators. These are actually in world-coordinate for (tk in ob.trk) if (tk.isSolved == 2 && tk.isExported) Tracker(tk) end end end // Point cloud is CONTROLS, not geometry. // The point cloud controls eventually get hung up in object mode, when the // outputis connected to an position-animated merge, so we animate the // point cloud, and leave its output unconnected function PointCloud(ob) pcnm = NM(ob.nm) pcc = 0 for (tk in ob.trk) if (tk.isSolved == 1 && tk.isExported && !tk.isFar) pcc += 1 end end if (pcc > 0) pcc = 0 Wire2Merge3D(pcnm "Cloud3D") Enter(pcnm "Cloud3D", "PointCloud3D") Enter("Positions", "") for (tk in ob.trk) if (tk.isSolved == 1 && tk.isExported && !tk.isFar) Define("[" pcc "]", "{ " tk.ox ", " tk.oy ", " tk.oz ", \"" NM(tk.nm) "\", }") pcc += 1 end end Exit() if (!ob.isCamera) Enter("Inputs", "") SetChan("Transform3DOp.Translate.X", 0) SetChan("Transform3DOp.Translate.Y", 0) SetChan("Transform3DOp.Translate.Z", 0) SetChan("Transform3DOp.Rotate.X", 0) SetChan("Transform3DOp.Rotate.Y", 0) SetChan("Transform3DOp.Rotate.Z", 0) Exit() end Plunk() Exit() end end // Far points are ok if the camera is stationary, ie in tripod mode, as // long as the point cloud can be placed on the camera location // Only active for stationary cameras, never objects function FarPointCloud(ob) pcc = 0 for (tk in ob.trk) if (tk.isSolved == 1 && tk.isExported && tk.isFar && stationary) pcc += 1 end end fpcnm = NM(ob.nm) if (pcc > 0) pcc = 0 Wire2Merge3D(fpcnm "FarCloud3D") Enter(fpcnm "FarCloud3D", "PointCloud3D") Enter("Positions", "") for (tk in ob.trk) if (tk.isSolved == 1 && tk.isExported && tk.isFar) Define("[" pcc "]", "{ " tk.ox ", " tk.oy ", " tk.oz ", \"" NM(tk.nm) "\", }") pcc += 1 end end Exit() Enter("Inputs", "") frame = startFrame SetChan("Transform3DOp.Translate.X", maincam.x) SetChan("Transform3DOp.Translate.Y", maincam.y) SetChan("Transform3DOp.Translate.Z", maincam.z) // Do NOT put rotation here! These in world coords SetChan("Transform3DOp.Rotate.X", 0) SetChan("Transform3DOp.Rotate.Y", 0) SetChan("Transform3DOp.Rotate.Z", 0) Exit() Plunk() Exit() end end function DoChannel(ob, chnm, atr, cr, cg, cb) docnm = NM(ob.nm) Enter(docnm chnm , "BezierSpline") String("SplineName", docnm chnm) Define("SplineColor", "{ " cr ", " cg ", " cb ", }") Define("NameSet", "true") Enter("KeyFrames", "") for (curfrm = startFrame; curfrm <= stopFrame; curfrm++) frame = curfrm cfrm = curfrm + bias act = ob .$ atr chval = ( "{ " act "," ); if (curfrm != startFrame) frame = curfrm - 1 pfrm = frame + bias pact = ob .$ atr pact = (pact - act) / 3 + act chval = (chval " LH = { " cfrm-0.3333 "," pact ", }," ) end if (curfrm != stopFrame) frame = curfrm + 1 nfrm = frame + bias nact = ob .$ atr nact = (nact - act) / 3 + act chval = (chval " RH = { " cfrm+0.3333 "," nact ", }, ") end chval = (chval "Flags = { Linear = true, }, ") chval = (chval "}"); Define(bquo cfrm equo, chval); end Exit() Exit() end //--------------------------------------------------------------------- // Note: trackers attached to a camera are WORLD coordinates, attached // to an object they are object-relative // TODO: This can be used to implement far, independent trackers function Tracker(tk) tknm = NM(tk.nm) frame = startFrame Wire2Merge3D(tknm) Enter(tknm, "Locator3D") Enter("Inputs", "") AnimChan("Transform3DOp.Translate.X", tknm "XOffset") AnimChan("Transform3DOp.Translate.Y", tknm "YOffset") AnimChan("Transform3DOp.Translate.Z", tknm "ZOffset") Exit() Plunk() Exit() DoChannel(tk, "XOffset", "wx", 0, 1, 1) DoChannel(tk, "YOffset", "wy", 1, 0, 1) DoChannel(tk, "ZOffset", "wz", 1, 0.706, 0) end function SetChan(nm, val) Enter(chs nm che, "Input") Define("Value", val) Exit() end function AnimChan(nm, val) Enter(chs nm che, "Input") String("SourceOp", val) String("Source", "Value") Exit() end //--------------------------------------------------------------------- function DoLight(lt) ltnm = NM(lt.nm) Wire2Merge3D(ltnm) Enter(ltnm, (lt.kind == "omni" ? "LightPoint" : "LightDirectional")) Enter("Inputs", "") SetChan("Transform3DOp.Translate.X", lt.x) SetChan("Transform3DOp.Translate.Y", lt.y) SetChan("Transform3DOp.Translate.Z", lt.z) SetChan("Transform3DOp.Rotate.X", lt.rx) SetChan("Transform3DOp.Rotate.Y", lt.ry) SetChan("Transform3DOp.Rotate.Z", lt.rz) Exit() Plunk() Exit() end //--------------------------------------------------------------------- // Called either at world coordinate level, or from within a parenting object // TODO: must offset the from the center to the base function DoMesh(msh) if (msh.kind == "TrackerMesh") return DoTkMesh(msh) end menm = NM(msh.nm) frame = startFrame Wire2Merge3D(menm) Enter(menm, "Shape3D") Enter("Inputs", "") if (msh.kind == "Sphere" || msh.kind == "Cube" || msh.kind == "Cylinder" || msh.kind == "Cone") lkind = ("Surface" msh.kind "Inputs") else lkind = ("SurfaceCubeInputs") end mxf = msh.trans level = 0.5*msh.sy if (msh.kind == "Plane") // mxf = RotX(-90) * mxf mxf = Transform(Vector(1,0,0),Vector(0,0,-1),Vector(0,1,0), Vector(0,0,0)) * mxf level = 0 end // Y-up adjustment of pivot point SetChan("Transform3DOp.Translate.X", mxf.x + level*msh.bx) SetChan("Transform3DOp.Translate.Y", mxf.y + level*msh.by) SetChan("Transform3DOp.Translate.Z", mxf.z + level*msh.bz) SetChan("Transform3DOp.Rotate.X", mxf.rx) SetChan("Transform3DOp.Rotate.Y", mxf.ry) SetChan("Transform3DOp.Rotate.Z", mxf.rz) SetChan("Transform3DOp.ScaleLock", 0) SetChan("Transform3DOp.Scale.X", msh.sx) SetChan("Transform3DOp.Scale.Y", msh.sy) SetChan("Transform3DOp.Scale.Z", msh.sz) if (msh.kind != "Plane") Enter("Shape", "Input") Define("Value", "FuID { \"" lkind "\", }") Exit() end if (msh.kind == "Sphere") DefineInVal(lkind, "Radius", 0.5) elseif (msh.kind == "Cylinder" || msh.kind == "Cone") DefineInVal(lkind, "Radius", 0.5) DefineInVal(lkind, "Height", 1.0) elseif (msh.kind != "Plane") DefineInVal(lkind, "Size", 1.0) end SetChan("MtlStdInputs.DiffuseRed", ((msh.color>>0) & 255)*(1.0/255.0)) SetChan("MtlStdInputs.DiffuseGreen", ((msh.color>>8) & 255)*(1.0/255.0)) SetChan("MtlStdInputs.DiffuseBlue", ((msh.color>>16) & 255)*(1.0/255.0)) Exit() Plunk() Exit() end // Handles tracker meshes, must be exported as a separate OBJ file, // brought into Fusion in a Filmbox node! function DoTkMesh(msh) menm = NM(msh.nm) frame = startFrame Wire2Merge3D(menm) Enter(menm, "SurfaceFBXMesh") Enter("Inputs", "") mfnm = BlastMesh(msh) DefineInput("ImportFile", "\"Comp:\\\\" mfnm "\""); DefineInput("[\"SurfaceFBXMeshInputs.Lighting\"]", 1) SetChan("MtlStdInputs.DiffuseRed", ((msh.color>>0) & 255)*(1.0/255.0)) SetChan("MtlStdInputs.DiffuseGreen", ((msh.color>>8) & 255)*(1.0/255.0)) SetChan("MtlStdInputs.DiffuseBlue", ((msh.color>>16) & 255)*(1.0/255.0)) Exit() Plunk() Exit() end // Create an OBJ file for this mesh, with a unique file name function BlastMesh(msh) // Break the export file down into a directory and basename, dump extension dir = "" basename = Scene.exportFile idx = fmax( rindex(basename, "\\"), rindex(basename, "/") ) dir = substr(basename, 1, idx) basename = substr(basename, idx+1) if ( (idx = index(basename, ".")) > 0) basename = substr(basename, 1, idx-1) end // Assemble a basename and mesh file name for this mesh. basename = (basename "_" NM(msh.nm) ".obj") objnm = (dir basename) // Here goes the file //"Name: " objnm "\n" openout(objnm) MeshOut(msh) closeout() return basename // this will go in the fbx node end //--------------------------------------------------------------------- function DoExtra(xt) xtnm = NM(xt.nm) frame = startFrame Wire2Merge3D(xtnm) Enter(xtnm, "Shape3D") Enter("Inputs", "") SetChan("Transform3DOp.Translate.X", xt.x) SetChan("Transform3DOp.Translate.Y", xt.y) SetChan("Transform3DOp.Translate.Z", xt.z) Enter("Shape", "Input") Define("Value", "FuID { \"SurfaceCubeInputs\", }") Exit() Exit() Plunk() Exit() end //--------------------------------------------------------------------- // Utilities function DefineInVal(noty, name, value) Enter(chs noty "." name che, "Input") Define("Value", value) Exit() end function DefineInput(name, value) Enter(name, "Input") Define("Value", value) Exit() end // Connect the input our_inp of the current node to the output // named src_outp from the src_node function SetSource(our_inp, src_node, src_outp) Enter(our_inp, "Input") String("SourceOp", src_node) String("Source", src_outp) Exit() end function Define(name, value) printf("%s%s = %s,\n", indent, name, value) end function String(name, stng) printf("%s%s = \"%s\",\n", indent, name, stng) end function Enter(kind, type) indent if (kind != "") kind " = " end if (type != "") type " " end "{\n" indent = (indent "\t" ) end function Exit() indent = substr(indent, 2) if (indent == "") "}\n\n" else indent "},\n" end end // returns 2: rot changes, 1: pos changes, 0: both stationary (3:both chg) function DoesTransformChange(ob) frame = startFrame tr0 = ob.trans pos0 = (tr0.rowP.x "," tr0.rowP.y "," tr0.rowP.z) rv = 0; for (frame = startFrame+1; frame <= stopFrame; frame++) tr = ob.trans pos1 = (tr.rowP.x "," tr.rowP.y "," tr.rowP.z) rv |= ((pos1 != pos0) ? 1 : 0) rv |= ((tr != tr0) ? 2 : 0) end frame = startFrame return rv; end // Check to see if the lens fov is fixed, indep of mode function IsLensFixed(cam) frame = startFrame fov0 = cam.fov //+ 0 for (frame = startFrame+1; frame <= stopFrame; frame++) if (abs(cam.fov - fov0) > 0.0001) return 0 end end frame = startFrame return 1 end function fix_slashes(slname) newname = "" for (chno = 1; chno <= length(slname); chno++) chr = substr(slname, chno, 1) if (chr == "\\") chr = "\\\\" end newname = (newname chr) end return newname end // removes spaces and anything else problematic from names--Fusion // doesn't like them. function NM(orinm) newname = "" for (chno = 1; chno <= length(orinm); chno++) chr = substr(orinm, chno, 1) if (index("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_ ", chr) == 0) newname = (newname "_") elseif (chr != " ") newname = (newname chr) end end return newname end // From the mshszn.szl exporter function MeshOut(msh) // make sure the same number of each are output "o " msh.nm "\n" nv = #(msh.vtx) nf = #(msh.face) sx = msh.sx sy = msh.sy sz = msh.sz rot = msh.trans rot.rowP = Vector(0,0,0) // kill the translation for (v = 1; v <= nv; v++) tv = msh.vtx[v] tv = Vector(tv.x*sx, tv.y*sy, tv.z*sz) * msh.trans printf("v %.6f %.6f %.6f\n", tv.x, tv.y, tv.z) end if (msh.hasTexCos) for (v = 1; v <= nv; v++) printf("vt %lg %lg\n", msh.texco[v].u, msh.texco[v].v) end end if (msh.hasNormals) for (v = 1; v <= nv; v++) nrm = msh.norm[v] nrm.x *= sy*sz nrm.y *= sx*sz nrm.z *= sx*sy nrm = nrm.norm * rot printf("vn %lg %lg %lg\n", nrm.x, nrm.y, nrm.z) end else for (f = 1; f <= nf; f++) face = msh.face[f] v0 = msh.vtx[face.vA] v1 = msh.vtx[face.vB] v2 = msh.vtx[face.vC] nrm = v1-v0 nrm = nrm.Cross(v2-v0) nrm.x *= sy*sz nrm.y *= sx*sz nrm.z *= sx*sy nrm = nrm.norm * rot printf("vn %lg %lg %lg\n", nrm.x, nrm.y, nrm.z) end end for (f = 1; f <= nf; f++) // f can be accessed by Slash face = msh.face[f] printf("f %s %s %s\n", Slash(face.vA), Slash(face.vB), Slash(face.vC)); end end function Slash(vn) vns = printf("%d", vn) res = (vns "/") if (msh.hasTexCos) res = (res vns) end res = (res "/") if (msh.hasNormals) res = (res vns) else res = (res printf("%d", f)) end return res; end