NavBar

Showing posts with label scripting. Show all posts
Showing posts with label scripting. Show all posts

Wednesday, April 20, 2011

PyMel

I print tshirts for a living, and that means that a good chunk of my work-day is spent waiting for the machine to spit out the next shirt. It gets pretty boring if I spend that time just sitting and waiting, so I get on my laptop and do useful things instead. This week, for example, I started to look into using PyMel for some of my scripting needs.

To get everyone up to speed, Maya uses its own embedded scripting language called MEL - Maya Embedded Language. It's a good start for learning how Maya works behind the scenes, but it is rather rigid in its structure, and has a tendency to be very very verbose.

Newer versions of Maya have begun to include a Python runtime as well as a library which ports all (most? I'm not 100% sure) of Maya's MEL commands for use in Python. This essentially allows you to write MEL code while taking advantages of some of Python's nicer features: dynamically typed variables, more refined string manipulation, and not having to check every freaking line of code for the one semi-colon you missed that's causing your whole script to break. However, it still requires you to think largely in more of a MEL-type flow, which ends up feeling like a half-baked hybrid that nobody really would want to look at.

That's where PyMel is intended to come it. From what I gather, PyMel is designed as a more Python-y integration of Maya commands into Python. Honestly, I don't have enough experience to say for sure, but at first glance it does seem to be an improvement. I will add one caveat: it appears that others more experienced than I have a less-than-enthusiastic opinion of PyMel, primarily because they have found it to become excessively slow for large iterative tasks. However, since I'm writing small helper scripts rather than full-on tools, the speed differences have so far been indistinguishable. (As a final aside, a brief websearch indicates that PyMel is faster overall for scripting control, but it is faster to then switch to the Maya.Cmds functions for iterating large loops.)

Anyways, why is all this important? Because I'm a perfectionist and a minimalist (usually within reason). I like to do as much as I can with as little as I can get away with. For example, why write 5 lines of MEL code when I can do the same thing with 1 line of PyMel?

//Parent constrain lower-level control object's zero-group to higher-level control object
//MEL Code
string $OA_ctrl_parent_selection[] = `ls -sl`;
string $parent_ctrl = $OA_ctrl_parent_selection[0];
string $child_ctrl = $OA_ctrl_parent_selection[1];
string $child_group = "GRP_" + $child_ctrl + "_zero";
parentConstraint -mo $parent_ctrl $child_group

//Parent constrain lower-level control object's zero-group to higher-level control object
//Python/PyMel Code
parentConstraint( ls(sl = 1)[0] , "GRP_" + ls(sl = 1)[1] + "_zero" , mo = 1 )

I'll be the first to admit that the PyMel snippet is much more difficult to decipher, but ultimately it's going onto my shelf as a button anyways. I'm also working on translating to PyMel the script I talked about in my previous post, but it's still a work in progress. In the end, though, I just really love writing these bits of automation to make my life easier. My rigging is already getting faster just by reducing the number of operations I have to execute to get the same results.

Sunday, April 17, 2011

Mech Rigs + Tool Writing


I've recently joined the Angels Fall First team as an animator, which is turning out to be a lot of fun already. I enjoy animating, but I love rigging and scripting, which is good since my first set of jobs are to rig (and eventually animate) the first big mech, the Velius Mk2, as well as some of the first-person arms and weapons. It's been a while since I've done any hardcore 3D work, so I've been shaking loose the cobwebs and getting back into my groove.

For the mech, I was given the in-game mesh weighted to an older version skeleton, but it was missing any sort of controls, and the existing animation had been baked down onto the bones. After looking the whole thing over, I scrapped the animation, detached the mesh, and went to work improving the skeleton. The original structure was mostly acceptable, but I added in some extra degrees of motion for the hips, torso, and neck, as well as bones for the toes. I also added in some bones which will be be used in-engine to facilitate the destructible armor plating.



Once that was finished, I weighted the mesh back onto the skeleton so it could move around. Weighting mechanical objects like a mech is a fairly easy process, since most of it simulates rigid binding, but it can still be tedious.


I then duplicated the skinned skeleton to provide a base for the control skeleton. My thinking was that by separating the control structures from the skinned skeleton, I could re-skin the mesh or fiddle with the rig controls without affecting the other too much. The two skeletons are exactly the same, except that the control skeleton has two sets of arms and legs to allow for IK and FK control sets.

Of course, a control skeleton isn't very useful without control objects for the animator to manipulate. Most rigs I've used in the past stick to NURBs curves for the controls, but I decided to mix and match. I'm experimenting with doing super-low-poly versions of the limbs instead of control curves because they are easier to spot and easier to click on. The arrow control curves were objects that I created quickly in Illustrator, saved as Illustrator 10 files for compatibility, then imported into Maya


With the control objects built, I now need to hook them up. The IK controls will be a little tricky, but FK controls are about as straightforward as you can get. However, connecting everything by hand takes a long time, so I wrote a little script to speed things up. All I have to do is select my control object, the joint I want to connect it to, and run the script. What it gives me is a control surface completely oriented to the joint with all its translation, rotation, and scale channels zeroed out. This gives the animator a nice, clean base to start with.

In all, getting to this point has taken me about a day and a half, and I loved every minute of it. I spent almost my entire weekend working this up because that's what I like to do. I'll post more shots as I finish it up. Also, go check out the Angels Fall First site! It's got a lot more cool stuff to look at!

Tuesday, April 6, 2010

I'm a tool (writer)

Things are getting pretty busy. The film is due for marks on Friday, and I'm busy trying to get something patched together for marks. To help try to meet that, I took some time today to write a little pair of tools to get me working faster.

The UDK has a nifty command switch called "dumpmovie" which forces it to save every rendered frame to the screenshots folder. In combination with the "fps XX" switch (where XX is the number of frames per second), it essentialy performs like a batch render in Maya, except there's not automatic off. Instead, it plays in a game window, and stops recording when you exit the game. Of course, the options with this are very limited. You can't (as far as I'm aware) set the path for the screenshots, and it only saves in BMP format, but it works, and that's what's important. Since BMPs are uncompressed, they take up a lot of space. A 120-frame render weighs in just over 300Mb. With WinRAR, I can collect and compress those 120 frames into a single 20Mb RAR file. That's about a 93% storage savings.

With those facts in mind, here was my workflow for rendering out a scene:
  1. Save final map and assets in UDK, then close editor.
  2. Open command prompt and type in really long UDK shell command to start a Dumpmovie render. (example: C:\UDK\UDK-2010-03\Binaries\Win32\UDK MapName -dumpmovie -benchmark -fps 24 -resx=1280 -resy=720)
  3. Render out scene.
  4. Open Explorer to the UDK screenshots folder.
  5. Select all new rendered frames.
  6. Right click, "Add to archive."
  7. Set up WinRAR options.
  8. Delete leftover frames.
Not optimal at all.

So instead, I wrote two simple batch files. One does the rendering side, the other runs the archiving. The rendering one also has the option of calling the archiver as soon as the render finishes. This is my new workflow.
  1. Run UDK_Render.bat.
  2. Give map name, choose resolution (full or half 720p).
  3. Run render.
  4. Choose to archive (or not).
  5. Give archive name.
  6. Done.
This leaves me with a screenshots folder that has nicely organized archives for each shot, plus it deletes the source files after creating the archive, so the screenshot folder is clean and primed for the next render. This also makes it very easy extract each archive into its own folder to prep for rendering out an uncompressed AVI from AfterEffects so I can then throw it into Premiere for editing.

As a side note for comparing UDK render time against Maya: If we assume Mental Ray is rendering at 5 frames/minute and UDK at 15 frames/sec, the ratio is 4500:1!!
Render time essentially becomes a non-issue. I could render my entire film (if it were contained in a single map), check for errors, tweak the map, and re-render in about the time it would take MR to render 3-5 frames. This by itself is one of my major arguments for using real-time rendering engines (like game engines) for rapid film production work.