FBX issues and such
Python FBX SDK Uses
Listed below are just a few things that you can modify in an FBX file with the SDK- Adding or removing properties/attributes
- Removing Namespaces before importing or after exporting
- Removing objects that were not a part of the specifically selected objects but were associated
- Removing textures or renaming paths
- Rename objects in fbx scenes without having to re-export the file from the source
- You can modify most anything in an FBX scene, external from a DCC application
Setting up the Python FBX SDK
http://www.autodesk.com/products/fbx/overviewHit the "Get FBX SDK" link and on the next page look for Python Binding. Choose your flavor, Windows, Linux, or Mac, download and install/extract the package. If you need an earlier version for compatibility reasons go to the "SDK Archive" link. I'm still using 2014.1 and it works fine with Maya 2014/2015/2016 and UnrealEngine 4.x.
You will need to install the package you have chosen to download. This package has a lot of incredibly useful samples for getting started with FBX in python and getting an understanding of the FBX scene in general. If you are at all familiar working with Python in Motionbuilder, pyfbxsdk, it is almost exactly the same and this should be quite easy to pick up.
Installing for Maya
If you are working in the latest versions of Maya 2014 and higher you will want the files in lib/Python27_x64 or x86. There are three main files that you will want to point to or add to your existing python paths for Maya.Here is a snippet to add to a script or your startup for Maya.
import sys sys.path.append(r'/FBXPath')These are the files that are needed:
fbx.pyd
FbxCommon.py
fbxsip.pyd
Here is some startup code for the FBX Scene Wrapper Class.
import fbx import FbxCommon class FBX_Class(object): def __init__(self, filename): """ FBX Scene Object """ self.filename = filename self.scene = None self.sdk_manager = None self.sdk_manager, self.scene = FbxCommon.InitializeSdkObjects() FbxCommon.LoadScene(self.sdk_manager, self.scene, filename) self.root_node = self.scene.GetRootNode() self.scene_nodes = self.get_scene_nodes() fbx_scene = FBX_Class(r'c:\my_path\character.fbx') # instantiate the classThe main thing to be aware of with most classes, is that you have to instantiate them to access their internal methods. Here we need to pass an argument that is a string of the fbx file path and name. The _init_ method will automatically parse and load the fbx scene. The one thing when parsing a file that you care about is speed, luckily when working with the Fbx SDK, even in python, I find it to be incredibly fast even on large Fbx files.
Now that the fbx scene is loaded we can go nuts changing the fbx file however we want. At Boss Key, after exporting I run a post process to modify all the fbx files, be it a character skeletal mesh, a weapon, or an animation file. I remove namespaces, empty display layers, remove objects that are in exported hierarchies that I don't want importing into UE4, or cleaning up any properties when necessary.
import FBX_Scene def clean_character_scene(fbx_file): """ Clean up character fbx file """ # open the fbx scenes and get the scene nodes fbx_scene = FBX_Class(fbx_file) if not fbx_scene: return False remove_names = [] keep_names = [] # remove invalid nodes noted by properties assigned in the DCC application all_nodes = fbx_scene.get_scene_nodes() for node in all_nodes: export_property = fbx_scene.get_property(node, 'no_export') if export_property: property_value = fbx_scene.get_property_value(node, 'no_export') if property_value == True: node_name = node.GetName() fbx_scene.scene.DisconnectSrcObject(node) remove_names.append(node_name) else: node_name = node.GetName() keep_names.append(node_name) # remove the nodes from the scene by name fbx_scene.remove_nodes_by_names(remove_names) # remove display layers # For some reason these change FbxCollection ID and NodeName layer_objs = fbx_scene.get_class_nodes(fbx.FbxCollectionExclusive.ClassId) if layer_objs: remove_layers(fbx_scene, layer_objs) # remove FbxContainers nodes = fbx_scene.get_class_nodes(fbx.FbxObject.ClassId) if nodes in nodes: if node.GetClassId().GetName() == 'FbxContainer': # disconnect the layer from the scene node.DisconnectAllDstObject() node.DisconnectAllSrcObject() fbx_scene.scene.RootProperty.DisconnectSrcObject(node) # remove display layers display_layers = fbx_scene.get_type_objects(u'DisplayLayer') if display_layers: remove_layers(fbx_scene, display_layers) # save the modified fbx scene fbx_scene.save() return True
Right after I run my custom fbx export method in Maya I will call a method, such as the one above, all in the same process. So when the artist is finished exporting they won't even know I opened up the fbx and modified it for the better.
The great thing about the FBX Python SDK is that you don't need a DCC application to run it. You can run standalone processes and modify all of your mocap or skeletal mesh files, renaming nodes, changing hierarchies or adding properties, all without having to return to the original DCC to reexport. Once you start working with the Fbx Python SDK you may never stop.
The Python SDK can process importing mocap before you actually import it into your scene and remove namespace issues. |
Once I got familiar enough with FBX SDK I started a project which became the Saints Row Mod Tools. I wrote the tool that converted fbx scenes into the file formats needed for Saints Row 3, and Saints Row IV for for modding purposes. Before we used custom plugins, tools and processes that would be far too complex to release to the community and support for multiple DCCs. Fbx covers all the bases so this was a worthwhile tool and the community seemed to appreciate it. If you want to download the python script that really digs into breaking down the fbx scene, feel free to hop over to the saintsrowmods forums and grab it.
My Public Gists (full examples from this post)
https://gist.github.com/Meatplowz
On a side note if you want to actually extend the plugins with C++ you can do so.
FBX SDK Plugin Extension
Let me know if you have any questions on the Fbx Python SDK. If you have any suggestions or tips yourself please share them as well.
Yes, like you I've found the FBX SDK to be super useful, approchable and fast. Thanks for sharing and reminding me that I've not used it nearly/creatively enough :-)
ReplyDeleteThanks for the info. I have started digging into the SDK and found it super powerful
ReplyDeleteHi Randall, thank you for the info, very valuable. I am tinkering with the FBX SDK but I cannot find the answer for a problem I have. I'm trying to reparent a node keeping its current world space xform. The issue is that using the FbxNode.AddChild method does this but keeps the relative transformation with its new parent, repositioning it. I am starting to dig into the FbxNode.EvaluateGlobalTransform() which returns the current world matrix (I guess) but I cannot find the code to put that matrix back to the reparented node. Do you know if it is possible to do that? Thanks in advance. Cheers!
ReplyDeleteSeems like It is not possible :(
ReplyDeleteFrom FBX SDK Documentation:
NOTE:A node's global transformation matrix of cannot be explicitly set in the FBX SDK.
https://help.autodesk.com/view/FBX/2017/ENU/?guid=__files_GUID_C35D98CB_5148_4B46_82D1_51077D8970EE_htm