AtomSplitter has been updated to v1.6, available through cmivfx.com
Updates:
- Exports Terragen .tgd scene file format
COMMAND LINE HELP
OSX:
AtomSplitter.app/Contents/MacOS/AtomSplitter <chan file> [out file]
Linux:
AtomSplitter <chan file> [out file]
Windows:
AtomSplitter.exe <chan file> [out file]
=========================================
HELP:
>>> AtomSplitter -h
Usage: AtomSplitter <chan file> [out file]
Options:
-h, --help
show this help message and exit
-o OBJ, --obj=OBJ
Optional nuke-exported pointCloud .obj file
-f FPS, --fps=FPS
Set FPS rate (default 24)
-x WIDTH, --width=WIDTH
Set frame width (default 2048)
-y HEIGHT, --height=HEIGHT
Set frame height (default 1556)
--filmwidth=FILMWIDTH
Set film aperature width in mm (default 24.576)
--filmheight=FILMHEIGHT
Set film aperature height in mm (default 18.672)
-s SCALE, --scale=SCALE
Scale the translation values by this amount
-F FORMAT, --format=FORMAT
Output format (fbx, action, terragen)

This is a story about my journey in solving a problem at work involving curves. The solution seemed really simple at first, but because of a stupid Maya issue, this turned into me having to rewrite the tool 3 times before I discovered a surprising solution.
The Problem:
Because we rely heavily on the process of importing Illustrator .ai files into Maya as nurbsCurves, we constantly have to deal with curves that intersect themselves. This is a result of the curves having been hand drawn originally in the art department, and they posed issues during rendering after being planar-ized.
We needed a way to detect self-intersecting nurbsCurves, so that we could fix them before working with them as nurbsSurfaces.
Getting started. I hate you, Maya:
The obvious place for me to start was to use the existing curveIntersect command. This command will tell you if two curves intersect, and at what points. Although it requires that you tell it 2 individual curves to test, I figured I could just split the single curve into parts (using detach curve), and pair off all the parts to test them. And here is where I ran into something that just pissed me off. While it works great to tell you where the intersection is… when it DOESN’T find an intersection, it prints a “Warning: Could not find curve-curve intersection” line. Printing to the script editor in maya is SUPER expensive as I have found. Everything slows down. This was the initial reason I decided not to use this method. I later found out the RIGHT hack way to deal with this is to wrap the entire process in scriptEditorInfo commands to suppress warnings being printed to the Script Editor and re-enable after. This method does prevent the amazing slowness, but still has the unacceptable flood of warnings once suppression is turned back off again. So even with this fix, I still found this approach to be too slow. For a single complex curve object that might have, say, 500 spans… that would be 124750 unique combinations that would have to be tested with the curveIntersect command. In a test of just looping that many times and calling this command, the process took 54 seconds! No way could this work, with a scene that could easily have 2000+ nurbsCurves!
Great. Now I get to investigate my own intersection detection from scratch.
Approach #2 – Brute Force
I’m a film school graduate… not a computer science major. Never thought I would have to use the kind of math I TRIED to implement for a first solution. Solving the cubic function of every curve segment to find the intersections? Meh. Too hard.
Next I thought of an idea to take a curve and sample N-amount of points from start to end parameter. So lets say 1000 samples. I would get 1000 points on the curve, then compare each point to the other non-neighboring points to see if they are within a distance tolerance of each other. If they are, I consider this a point in the curve where it looped and self-intersected. This method did work. It was still not super fast, but no where NEAR as slow as using the intersect command. I built in some dynamic scaling of the sampling and tolerance to accommodate for curves of different size and complexity. Even though I had to test 499500 point combinations per nurbsCurve for the 1000 point samples, this was only math and not a repeat call to curveIntersect. Ultimately, I was still not where I needed to be in terms of usability. A complex curve could still be a few seconds to test. Still too slow.
Approach #2.5 – Brute Force mixed with a fast little pre-check
Amongst the tons of search results I waded through on google, I found a really cool little trick someone came up with: http://forums.cgsociety.org/archive/index.php/t-517347.html
He suggested a cool hack where you planar the surface, then convert it to polygon with certain options, and then count the number of resulting faces that were produced. Theoretically there should only be 1 face if the curve never intersected itself. If it did, those loops should also have faces.
Well then, why couldn’t I just use this method as my detection algorithm? While it was pretty darn fast since no iteration is involved, I discovered a few limited cases where I was getting False Negatives: The method said there was only one face (no intersection) on a curve that actually did have a self intersection. So I decided to use this as a pre-check to save time. If it DID say there was self-intersection, great! Log it. Otherwise, slow test it with the brute force method.
Approach #3 – Math that I never learned
At this point I had accepted the solution for detecting self-intersection, and moved on to writing a maya UI for the tool. It would detect loops and optionally even report back the best estimate to the point where it actually occurred. But once I started writing another bigger tool that would use this script, I just knew it could be done faster with the power of math and without the poop of maya script command calls.
I discovered a paper written about a method called “Bezier Clipping” : Curve intersection using Bezier Clipping
For this method to be used on a single curve, one would first need to split the curve into its segments, in my case producing a bunch of cubic curves. With each pair of combinations, a bounding box check would be performed. If the bounding boxes do not overlap, you are done. No intersection would have occurred. If the bounding boxes did overlap, then you would start drilling down the check by clipping away sections of the curves outside the bounding box overlap. You can discover the intersection pretty fast by either drilling down until the segments are small enough to represent the single point, or the segments are now small enough to be considered linear and a you can use the slopes to find the intersection.
I was really stoked by this idea. The paper made it look really straight forward. I ended up writing a really cool custom wrapper around a nurbsCurve object that could represent a sub-section of the curve, and could easily give me things like the length and parameter range. It had a split() method that could split the curve at a given length or parameter and give me back two sub-curves, of which each could further be split. This class was integrated into the Bezier Clipping method and I finally got it all working. The initial tests were amazingly fast, but I ended up finding that the process became quite slow on large numbers of complex curves. I attribute this to my implementation of the bezier clipping, not the method itself. I didn’t take the time to actually generate proper sub-segments based on the bounding box overlap, and instead just did a simple 50/50 split of each curve, and tested the new combinations. I think I was just so bummed about the performance results that I didn’t feel like making the improvements to the process would make enough of a difference. What I had now was ultimately slower than my brute force method when tested against an entire scene of curves. So I decided to just go back to that.
Approach #4 – The unexpected trick
Whilst working on the larger project meant to make use of the loop detection script, I discovered something amongst the curve commands. offsetCurve includes the function of clipping away loops while creating the new offset curve object. My idea was to create an offsetCurve with the minimal changes, at a zero distance, so the curves would be right on top of each other. Then I could just compare the area/length/etc attributes of the curves to see if there was a change. This was really fast and really accurate, down to the smallest loops. Right now I’m comparing the area and length values rounded to a certain tolerance. This method was amazingly fast, and a fraction of the code.
The only minor downside was I found that because of the rounding I needed to do to compare the values, every so often a couple curves would be found as self-intersecting when they were not. Thats much better than MISSING curves during the detection. So what I did was combine the earlier face-counting solution with this one, to fail over between the two. The combination was really fast and accurate, without 100,000 warnings showing up in the stupid script editor.
All in all
I’m really surprised how many versions of this tool I had to write, to ultimately end up at a really simple one. I never would have thought to look at this offsetCurve command for a solution. Had to dig into some math I never thought I would use, also. So THATS what those stupid polynomial equations were for?

I recently did an interview with my friends on their show, Film Jam. Its a podcast dealing with the film industry from the perspective of 3 guys working their way up the ladder. Fantastic show up ’till this point. Hopefully I don’t break the cycle
Please make sure to leave a review about the show via iTunes!
Episode #20

AtomSplitter has been updated to v1.5, available through cmivfx.com
Updates:
- Added the ability to convert point cloud data, exported from Nuke as a .obj, to be included in the fbx/action export.
AtomSplitter (chanToFbx) has been updated to v1.2, available through cmivfx.com
Updates:
- Camera rotation order set to ZXY, which is the Nuke camera default
- Fixed a bug where the FocalLength value was not being keyframed properly
- Added a scene scale field, for adjusting the translation values globally.
If you haven’t visited cmiVFX.com before, PLEASE check them out. Chris Maynard does an amazing job rounding up top talent in the industry to create these outstanding visual fx tutorials. The information is always cutting edge.
“App’ing up” PyQt… ugh.
One of biggest problems with PyQt is distributing it in a stand-alone package. Even worse… wanting to make your Qt plugins still function (Phonon, jpeg, etc). At work I constantly had this battle, along with my co-worker Tory. She actually has a long-standing issue with this, and had to resort to workarounds or half fixes. Here is Tory’s original post regarding the issue .
I would see an error similar to this when trying to package up and run an app using the Phonon module.
WARNING: bool Phonon::FactoryPrivate::createBackend() phonon backend plugin could not be loaded
Running macdeployqt myAppName.app does add things like the jpeg plugin, but never seemed to fix the Phonon issue. I finally decided to randomly look online for a solution, again, last week. What I found was a partial solution, followed by me trying one more thing and bam…it worked! Video playback from my .app standalone package.
Here is what I did …
(btw you might have to modify the location of the plugin, since I happen to be using OSX)
- In your setup.py file, which is used for py2app, py2exe, or similar… add this to the DATA_FILES list, so that it looks as such:
DATA_FILES = [('phonon_backend',
['/Developer/Applications/Qt/plugins/phonon_backend/libphonon_qt7.dylib'] )]
This will put the phonon backend plugin into the RESOURCES folder in the app. - Package up your application via py2app / py2exe / etc.
- If you are on OSX, use macdeployqt on the app:
>>> macdeployqt myApp.app - Go into the app that was created (show package contents if you are on a mac), and move the phonon_backend directory FROM the Resources directory TO the PlugIns directory (which should be at the same level as Resources).
That should be it!

I get to do a lot of interesting applications at SouthPark. This one in particular was the most challenging use of PyQt that I have experienced to date.
The backstory….
The art department wanted a tool to help them track assigned tasks, the progress, and to share media and notes associated with the tasks. Furthermore, they wanted to be able to skin the interface with custom graphics to make it their own.
Progress…
During the winter break (about a month) I was able to come up with version 1.0 of TaskMonster. It was written in python, using PyQt for the UI, sqlalchemy to talk to the database, and twisted for the client/server communication. Each client app sends messages to a small server daemon which in turn tells the rest of the clients about the updates.
Version 2.0 Alpha…
Tony Postma, from the art department, put together a design in Corel which I could hopefully implement in the UI. It called for the users to be represented as little pods in a circle around the supervisor, Adrien Beard. And each user pod could be clicked and rotated into place, in order to view that persons tasks.
After a bunch of testing I was able to design a rotating widget that could dynamically lay out N widgets around it in a circle, track their position, and jump to any other widget. I was also able to break down the corel->illustrator file, into a combination of SVG and PNG images, and skin the UI via CSS stylesheets.
Its currently an alpha release. I guess I need to really learn how to control the widget painting, to make it faster. Never had to do this much before.
What I came up with… Click here to watch the demo video

You know when you have all these widgets laid out in your class, and you are hooking up all the connections, and you say “Aw dammit I have to subclass QLabel now just so make it ignore blahEvent”? You end up with all these little widget subclasses, where all they are doing is ignoring an event.
I noticed I was doing this a few times, in more than one of my classes, and finally got annoyed for the last time. I figured there had to be a simple way of just overloading the method on the normal object when I create an instance. Fortunately python considers everything objects and pretty much anything can be changed. So I did this:
myLabel = QLabel() myLabel.mousePressEvent = lambda event: event.ignore()
Magic.
I have also had to make clickable widgets, such as QLabel:
myLabel = QLabel()
myLabel.mousePressEvent = lambda event: myLabel.emit(SIGNAL("clicked"))
Or if you had to do more than just a single statement:
myLabel = QLabel()
def clickedEvent(event):
myLabel.emit(SIGNAL("clicked"))
# do other stuff
# do stuff
event.accept()
myLabel.mousePressEvent = clickedEvent
I like this better than piling up subclasses that don’t do much.
I had a project where I was designing a statistics reporting site, to track production stats. I wanted to have really nice graphs that pulled from the database and were somewhat live and interactive. XML/SWF Charts is this awesome flash-based app that lets you embed graphs in your pages which receive their data from XML. There are tons of graph types and ways to customize the look.
http://www.maani.us/xml_charts/index.php
So, the thing is… I wanted to use Django for the site. I decided to write a python module that wraps around the API for SWF charts, so that the XML could easily be generated for me after just setting all my parameters. Thought I might post this here for any python fans wanting nice looking graphs in their site.
Really, this doesn’t just apply to django. You could just call out from anything to python code that will generate your XML for you.
Example:
chart = SwfChart()
# the data
chart.addRow( 'Person A', 1, 10, 5.5 )
chart.addRow( 'Person B', 6, 4.45, 8 )
chart.addColumnLabel( 'Day1', 'Day2', 'Day3' )
# Extra graph settings
chart.addFilter('shadow', 'low', distance=2, angle=45, alpha=35, blurX=5, blurY=5)
chart.addFilter('shadow', 'high', distance=3, angle=45, alpha=35, blurX=10, blurY=10)
chart.addFilter('bevel', 'bevel1', strength=10, quality=3, distance=2)
chart.setChartBorder(top=1, bottom=2, left=0, right=0, color='000000')
chart.setChartLabel(color='000000', alpha=80, size=8, position='outside', hide_zero=True)
chart.setChartTransition(type='scale', delay=.5, duration=.5, order='series')
chart.setChartRect(shadow='high')
chart.setLegend(size=12, alpha=90, fill_alpha=30)
chart.setAxisTicks(category_ticks=True, value_ticks=True, minor_count=3)
chart.setContextMenu(about=False)
# if you have the licensed version
chart.setLicense('license string')
Now at this point, the object can be treated like a string to get the xml, or just call getXML() :
print chart print chart.getXML() # same thing xml = str(chart) # or assign the XML string somewhere
You can download the swfcharts.py module and use it freely. If you find it helpful, post a comment or shoot me an email.
Download swfcharts.py
Pydoc located here for convenience: swfcharts python documentation
I never thought I had known such a real sense of failure until today, when a system diagnostic became intent on showing me just how hard of a failure we will be experiencing together.
This is probably the hardest system failure I have ever felt.
The system failed so hard, I was actually sent home from work for the day, and the system called my mom on the phone to inform her just how much of a failure this was. They scheduled a Parent-System conference for next week.





