The Power of Python
Almost anything is possible in code, given enough time. However given the right technologies and libraries then coding can be quick and easy! Python is a great example of this. The Python standard libraries make many programming tasks that are time consuming and error prone in C++ very easy. For example creating a web-server and converting numerical data to JSON.
At Autodesk University I gave a demonstration of a Python API that served 3D content in JSON to a web-browser. After giving the demo I realized that just showing JSON data in the browser is a bit underwhelming, so decided to render the JSON data using WebGL and to extend the API to the FBX SDK as well.
The point of the demo I gave at AU was not the web-server, but rather to show how easy it is to build a cross-product Python API around the various M&E SDKs. For this blog post I'm going to skip the details of the cross-product Python API and focus on a particularly interesting part of the demo: serving 3D content over the web from a FBX file using nothing more than the FBX Python SDK.
What you need to know about the cross-product Python API I made is that it is in a Python package called "autodesk". When this package is imported it looks at an environment variable in order to load the correct abstraction layer. In this case the wrapper around the FBX Python API "fbx_common". Effectively it is a wrapper around the FBX SDK.
Running the Scripts
The following video and steps show how to run the 3D web-server scripts using the FBX Python SDK.
- Install Python 2.6 (2.7 isn’t supported)
- Download the FBX Python SDK
- Install it (see these instructions)
- Unzip this zip fille containing the scripts (attached to this blog post) and copy it to a local folder on your machine (let’s call it “server3d”)
- Create a PYTHONPATH environment that has the path to the “scripts” folder as its value.
- If PYTHONPATH already exists append the path using a semicolon (';') to separate it from the previous value.
- Open up the Python 2.6 console in your "server3d" directory
- Type in:
import fbx
- This is just to check that your FBX SDK is installed correctly.
- If nothing happens then it worked
- Type in:
dir(fbx)
- You should now see the contents of the fbx module.
- Type in:
import init_autodesk_fbx
- This is required only once per interpreter session
- It must be done before loading the “autodesk” package
- Type in:
import os
- Now type in:
print os.environ['ADSKPRODUCT’]
” - You should see the word “fbx” output on the console.
- Now type in:
- Type in:
import autodesk
- Now try:
autodesk.app.write_line('hello world')
- This should write the text “hello world” to the console
- Now try:
- Type in:
autodesk.app.load_file('teapot.fbx')
- If the file load is successful you will see “True” on the console.
- If the file load is unsuccessful then provide the full path to the file (don't forget to escape your backslashes: '\\')
- Type in:
import output_scene
- Now type in:
output_scene.output_scene()
- You should see information about the contents of the file on the console.
- Now type in:
- Type in:
import server3d
- Now type in “
server3d.serve()
” - If you have a firewall you may need to create an exception for Python on port 8000
- Now type in “
- Open a web-browser (Safari, Firefox, or Chrome), and set the url to
http://localhost:8000/test
- You should see in your browser “This is a test. You are running Autodesk FBX”.
- At this point it is normal that your Python console becomes unresponsive, because its main thread is busy running the web server.
- Set the browser url to
http://localhost:8000/tree
- You should see a text representation of the node graph in your FBX file
- Set the browser url to
http://localhost:8000/mesh
- You should see a list of numbers in JSON format containing mesh-data for the first object in the scene graph.
- Set the browser url to
http://localhost:8000/demo
- This tells the server to serve the HTML file “demo.html” which in turn will request the mesh data
- If you have a WebGL enabled browser you should see a page with a 3D representation of an object
- Set the browser url to
http:///localhost:8000/exit
- This will shut down the web server
If everything worked out for you at this point you can start having fun playing with scripts and adding new features. The files you probably want to look at in order are:
- output_scene.py - Simple example of using the cross-product API to output scene information
- server3d.py - A web-server that serves 3D web content that runs on multiple products.
- autodesk/base.py - Documentation of the object model used by the cross-product API.
- autodesk/fbx_common.py - The FBX python layer.
- demo.html
How the Web Server Works
The server3d uses an instance of the default TCPServer class in the Python library and a custom HTTP request handler derived from BaseHTTPServer.BaseHTTPRequestHandler
. The custom request handler looks at the URL of HTTP "GET" requests, and depending on the text chooses to serve different content. The HTTP response is handled by writing to a member variable of the base class called "wfile".
When the URL contains the text "demo.html" (e.g. http://localhost:8000/demo.html") the contents of the file "demo.html" is copied to the "wfile" member variable. When served to the web-browser, a JavaScript function in that file will send an XmlHTTPRequest back to the web-server for mesh data:
// Request the mesh data from the web server
req = new XMLHttpRequest();
req.open("get", "mesh" + qs, false);
req.send();
var json = JSON.parse(req.responseText);
When the server receives a URL containing the text "mesh" it will return a JSON representation of the mesh data.
# Return a JSON representation of the mesh of the first selected object or the named object.
elif '/mesh' == path:
try:
# Check is a node name has been specified
if 'name' in params:
name = params['name'][0]
node = node_by_name(name)
else:
node = autodesk.app.first_selected
if not node:
node = first_node_with_mesh()
jsondata = node_mesh_to_glge_json(node)
except:
jsondata = 'Exception: ' + exception_string()
content.write(jsondata)
I could go into more detail, but I think reading and experimenting with the code is the most effective thing you can do.
Final Words
I hope this inspires you to start thinking about new and interesting ways to use the FBX Python SDK!
Note that the server3d.py module should work also from 3ds Max 2012 Subscription Advantage Pack using an update Python script launcher plug-in and from MotionBuilder 2012 and Maya 2012. In 3ds Max the environment variables needed by the "autodesk" pacakge are set by the Python plug-in, but for MotionBuilder you will have to call "import init_autodesk_mobu
" and for Maya you will have to call "import init_autodesk_maya
" before importing the server3d module.