<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-19305204</id><updated>2011-04-21T21:28:43.201-07:00</updated><title type='text'>An Old Dog learns new tricks</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://car2ns3d.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19305204/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://car2ns3d.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Stephen Greenberg</name><uri>http://www.blogger.com/profile/16640921787080104112</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>19</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-19305204.post-116769491441591433</id><published>2007-01-01T14:41:00.000-08:00</published><updated>2007-01-01T15:41:54.506-08:00</updated><title type='text'>Damn!</title><content type='html'>I've been looking at my early scripts I've written for my own use and my job. I now see a lot of ways to make those scripts a lot more efficient, or at least shorter.&lt;br /&gt;&lt;br /&gt;It seems I've written 14,000 lines in scripts in the last year or so. Jeebus but that's a lot of updating I'll need to do. Most likely, when I leave my current job.&lt;br /&gt;&lt;HR&gt;&lt;br /&gt;Some interesting tools I've written lately:&lt;br /&gt;Transfer shapes and connections from an outsourced facial rigs to the most recent company models and rigs, then delete the outsourced character model.&lt;br /&gt;&lt;br /&gt;Face control and face camera windows that don't allow the other characters to interfere. Each has a pull down menu with the names of all the referenced characters n the scene. There's also a checkbox on the face camera to turn off orthographic front view so the face can be rotated around, and an adjustable clipping plane in the non-orthographic view to clip out interfering body parts.&lt;br /&gt;&lt;br /&gt;A more specialized user interface for loading and saving the outsourced work so it'll more easily transfer to referenced characters.&lt;br /&gt;&lt;br /&gt;A floating tool window with the tools likely to be used by other people.&lt;br /&gt;&lt;br /&gt;A new, simpler FBX2Maya tool that expects the FBX rigs to actually be updated to the current rigs.&lt;br /&gt;&lt;br /&gt;A multi-proxy tool that puts all the lores proxies in one group, and all the hires proxies in another. It's stupid how by default Maya makes a wordily named group for each object, making it more difficult to access them as a group in their lores and hires manifestations.&lt;br /&gt;&lt;br /&gt;I made a tool for eye movement. It can simulate small eye movements to get rid of that cg "dead eye" look, with presets for camera angle and character emotional state. Sliders allow more fine tuning of eye movement magnitude and timing. Keyframing tools that allow an eye direction to be set on any selected character in the scene, but doesn't use a wired target that hangs in space (meaning multiple retargets and keys need to be used when the head is moving, but it eliminates that creepy "sliding eye" thing) with adjustable range for working on smaller segments of the overall scene, and sliders to adjust the eyes, buttons for adding keys or deleting them. I might make a version someday that also does eyelids with similar timing controls.&lt;br /&gt;&lt;br /&gt;Nice thing about the tool is you can always edit the channels for more individualized control, but it gives a nice leg up for a quick and usable sub-eye movement when time is short. Sometimes there just isn't time to hand key everything that needs it.&lt;br /&gt;&lt;br /&gt;While I was testing my face control tools, I needed to mock up a face controller real quick, so I created a face control maker tool. This makes two dimensional geometry boxes with moveable geometry in the middle limited to the interior of the boxes, text to identify them, and a slider to make it all in scale to the character. I might add a control interface to hook the controls up to channels later.&lt;br /&gt;&lt;br /&gt;Updated crapBeGone to a scorched earth version that leaves the skinning intact with a separate button. crapBeGone eliminates unused nodes (for real) as well as other cruft, which the built in Maya tools just don't seem to do.&lt;br /&gt;&lt;br /&gt;Been working on final skinning strategies now that models seem to be stabilizing and things might actually be moving into the Maya side of the pipe. Up to now, rigs have had to stay pretty simple so they'd be compatible with Motion Builder. I'm now working on rigs that can employ wrap deformers and other Maya-only trickery. Because of the large number of characters, we'll probably eschew dynamics and just leave the secondary stuff to hand keying, which seems to go really fast with a knowledgable animator at the stick. You'd think it would be faster to do the stuff with dynamics, but setting up dynamics for expected results takes a lot longer than the hand keying would on any given character. I've also been working with one of the animators to develop topological control of various aspects of the characters.&lt;br /&gt;&lt;HR&gt;&lt;br /&gt;Well, that's the update. I kinda wanted to take my blog off the "non-updated blog" list ;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19305204-116769491441591433?l=car2ns3d.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://car2ns3d.blogspot.com/feeds/116769491441591433/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19305204&amp;postID=116769491441591433' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19305204/posts/default/116769491441591433'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19305204/posts/default/116769491441591433'/><link rel='alternate' type='text/html' href='http://car2ns3d.blogspot.com/2007/01/damn.html' title='Damn!'/><author><name>Stephen Greenberg</name><uri>http://www.blogger.com/profile/16640921787080104112</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19305204.post-115359698777237795</id><published>2006-07-22T11:58:00.000-07:00</published><updated>2006-07-22T12:36:27.813-07:00</updated><title type='text'>The other part of my job</title><content type='html'>All the stuff I mentioned in the previous post is part of the job I've kind of had to take handling the animation pipeline. There's just no one else to handle that.&lt;br /&gt;&lt;br /&gt;Those familiar with Motion Builder might wonder why we're exporting skeletons. The answer is simple: It's a safety check. The director has signed off the performance in Motion Builder. By having the MB skeleton, it provides a visual cross reference as proof that the performance of the Control/IK version of the character is a 1:1 match with the approved performance when there's no divergence between the two skeletons, except maybe small spacial differences between dissimilar rigs used in the mocap process. Even so, when there's time the most recent version of the character is "characterized" in MB, so the match is pretty close to start with.&lt;br /&gt;&lt;br /&gt;But here's an example of how far astray this process can go: We had a scene mocapped with an early version of the character, and that pipeline skipped Motion Builder entirely. So all the hand animation done on top of the mocap was done in Maya. The system I came up with works with that as well. Even though in the latest version of this particular character, the rotations on the bones have been zeroed and realigned, the control structure is entirely different, and even the locations of the joints has changed. So part of the job of my conversion system is to take legacy animation and load the most recent versions of a character with that legacy animation. It's a really useful hat trick.&lt;br /&gt;&lt;br /&gt;OK, which brings me to the job I was actually hired to do: rigging. Lately I've been working on a facial rig architecture, that doesn't depend on blend shapes. I had to try a lot of things and burn them to the ground, because every one of them had some annoying pathology. 6.5 doesn't have the ability to paint weights on wrap or wire deformers, and influence objects give me a little more control over weight assignment, at least for the whole curve I'm using for deformation. It was pretty hard to figure out how to get the rotational information of the curves to be picked up by the object when the character is reoriented, but it was only hard because I had no idea what I was doing at first ;)&lt;br /&gt;&lt;br /&gt;But there are lots of other little issues that need solving. Things that should be cloth simmed won't be, like a character's leather jacket. Leather isn't like other kinds of cloth, and it presents special challenges. Fortunately, I have about 10 leather jackets to use as reference.&lt;br /&gt;&lt;br /&gt;Another is the typical problem of the shoulder area. It isn't hard to defeat some of the problems, but some of the actors who were used in the mocap sessions are [i]limber[\n]. Human limitations weren't a concern to them, and I have to accommodate the exceptional flexibility of a contortionist. As my supervisor says, "Fun, fun, fun". I'll probably be using influence objects a lot to create a selective "muscle system" where these problems occur. I've also got overlapping joints to accommodate controlled twist, a finger control system that accommodates mocapped finger data but lets you animate on top of it and a lot of little tweak controls that will let an animator or TD solve all sorts of problems with the character's, most of whom are not human proportioned. &lt;br /&gt;&lt;br /&gt;One of the things I have to deal with, is that with all these multiple characters, I can't use scriptJobs to pull off some of the character TD's magic tricks. I'm working on ways around that. But at least I've now boiled the rigging process down to a "one button operation" for the main controls, connections, constraints and expressions. The face and assorted compensation controls are the only part that has to be done by hand. &lt;br /&gt;&lt;br /&gt;It's all getting pretty exciting. At least in that way that a TD's job can be exciting.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19305204-115359698777237795?l=car2ns3d.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://car2ns3d.blogspot.com/feeds/115359698777237795/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19305204&amp;postID=115359698777237795' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19305204/posts/default/115359698777237795'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19305204/posts/default/115359698777237795'/><link rel='alternate' type='text/html' href='http://car2ns3d.blogspot.com/2006/07/other-part-of-my-job.html' title='The other part of my job'/><author><name>Stephen Greenberg</name><uri>http://www.blogger.com/profile/16640921787080104112</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19305204.post-115359463563885535</id><published>2006-07-22T10:32:00.000-07:00</published><updated>2006-07-22T11:57:15.686-07:00</updated><title type='text'>Finally getting down to brass tacks...</title><content type='html'>I'm finally starting to get some real scenes to work with. And my animation tools are getting a trial by fire.&lt;br /&gt;&lt;br /&gt;What I found out: Reality is always different from the test cases.&lt;br /&gt;&lt;br /&gt;First, the skeleton fbx files that I'm getting have joints differently named from the standard, with two characters in the scene. One character will have joints named with a suffix like ...J_1 instead of ...J. The tools were set up to look for _J, and when they're differently named, that a problem.&lt;br /&gt;&lt;br /&gt;Second, those suffixes weren't always consistent within the character. The ball of the foot and toe would sometimes be just _J where the rest of the character had J_1. So with two characters in the scene, one would have J_1 for everything and one would have J_2, but their toes and balls of the feet would be _J and J_1 respectively. Pain in the butt.&lt;br /&gt;&lt;br /&gt;Third, my method for loading a saved animation file saved under one character name or reference to another that might be referenced or not, or dissimilarly named joints or controls, required hand matching from the name used in the file to each joint or control in a character. There are a lot of controls and joints in characters. This would take a long time in practice even though I'd only have to do it once. It turns out that there is no luxury of time unless I want to put in a lot of OT to get things done, and I sometimes have minutes instead of hours to do things. &lt;br /&gt;&lt;br /&gt;Fourth, one method I had for handling conversion of mocap data to a fully rigged IK character worked, but when I'd try to save the referenced file would crash Maya as soon as I'd go to save the scene.&lt;br /&gt;&lt;br /&gt;Fifth, that method required separating the characters from the converted fbx scene into individual characters. This turned out to be time consuming also. &lt;br /&gt;&lt;br /&gt;So I needed to make tools a one stop affair. &lt;br /&gt;&lt;br /&gt;I created a new tool which would save the exact spacial location, regardless of hierarchy, of the IK character's driver transforms and rotation order. This could be used to convert the data from the mocap characters, even if they were based on a different skeletal setup and hierarchy. This file fits into my .sganm file format (which currently has three different versions that are automatically detected: ANIMATION which saves all of the keyframe data including tangents, tanget type, tangent weight, and infinity and is hierarchy dependent; MOCAP, which is just the raw keyframe number, and keyframe value for each channel and is still hierarchical; and a spatial location format that just puts everthing exactly where it is in the animation file in world space, which is non hierarchical but has to be implemented in hierarchical order or it results in a transporter accident. In otherwords, I already had a tool that could be deployed to store the data from the new rig. I save this in the master folder that contains the character's old mocap rig, new mocap rig and the IK character that has all the controls installed.&lt;br /&gt;&lt;br /&gt;In order for all this to work, the two skeletons have to be aligned on frame zero in the hero pose. The same code that's used for the translation from one older state to a newer one, or joint based animation to control based IK animation, is also used to create a master "zero frame" hero pose file. This is also stored in the master directory.&lt;br /&gt;&lt;br /&gt;I wrote a tool for automatic creation of a "map" file. This would use TD defined wildcards to match similarly named joints and controls to the one used in the animation file. Whether that file is a "zero frame" hero file, or a control location file. This worked great until I found the joint naming inconsistency. &lt;br /&gt;&lt;br /&gt;So I need to create a "descendants" based system that looks for matches regardless of the added delimiters and indexing based on the selected character name. I have bits and pieces of the code in use for other purposes, so it should be too difficult to implement.&lt;br /&gt;&lt;br /&gt;On top of all that, even if I get it all working smoothly, there's still the problem of the manual handling of the various steps in the conversion process. What's needed is yet another file format, this one being a "Rosetta Stone" so to speak, for all the characters that have that control space file and "zero frame" file already saved in the master directory. That way, I could load an fbx scene, select the characters in that scene from a list, and it would automatically set a zero frame, load the appropriate reference file for each character, and map the animation to the character with controls with a "one button push" and could be used by anyone, rather than having to have it done by a TD.&lt;br /&gt;&lt;br /&gt;There are a lot of details to making a system like that work. But I figure it could take a half hour of hand messaging and turn it into maybe five minutes. Which would be good since there are 1400 shots.&lt;br /&gt;&lt;br /&gt;The reason all this is necessary, is that Motion Builder doesn't handle the complex rigs with all their constraints and esoteric expressions, at least not the versions we're using in production. The rigs also can overload hand animation over the mocap, and have space switching capabilities, and MB can't handle those either, and you can't apply the motion directly to the joints because of the IK, so conversion is an absolute necessity.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19305204-115359463563885535?l=car2ns3d.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://car2ns3d.blogspot.com/feeds/115359463563885535/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19305204&amp;postID=115359463563885535' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19305204/posts/default/115359463563885535'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19305204/posts/default/115359463563885535'/><link rel='alternate' type='text/html' href='http://car2ns3d.blogspot.com/2006/07/finally-getting-down-to-brass-tacks.html' title='Finally getting down to brass tacks...'/><author><name>Stephen Greenberg</name><uri>http://www.blogger.com/profile/16640921787080104112</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19305204.post-114816736740410921</id><published>2006-05-20T15:08:00.000-07:00</published><updated>2006-05-20T16:27:28.016-07:00</updated><title type='text'>More tools, interfaces and refinements</title><content type='html'>I've been writing some minor tools, and going GUI crazy the last couple of weeks.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 204, 255);"&gt;Removing Print Commands&lt;/span&gt;&lt;br /&gt;After the discovery of how major an effect using the print command has, I decided to go through all my major scripts and removing print commands from them. Unless I'm debugging I don't need them. I also added a "Done" window that tells me how long a script takes to my longer scripts like the Animation Save/Load utility, and the spur to joint utility.&lt;br /&gt;&lt;br /&gt;In the process, I created a new standalone script called printWin. It consists of three processes: printWin initializes the script, you invoke "addPrintWin &lt;variable&gt;" to add the contents of a variable to a line in the text scroll list, and showPrintWin to show the window. I didn't combine the commands because I don't want the window to show up until all the data is added, and I don't want to add showWindow to addPrintWin because it can be used in highly iterative loops, and I don't want to call showWindow over and over again hundreds of times.&lt;br /&gt;&lt;br /&gt;I also added a log utility to the printWin window, so I could highlight some or all lines and then save them out to a log file for copying, pasting and testing if there's a malfunction. I can also open it in a text file to search for problem lines in thousands of commands to figure out what the problem is. The name and path of the log file can be changed.&lt;br /&gt;&lt;br /&gt;This is how I located a problem with my venerable "spur to joint" script, a major script that takes all the vertices in a character, analyzes their weights, removes them from spurs and adds them to the parent bone's weight assignment. Even if it doesn't have any weights assigned to it (which is pretty typical).&lt;br /&gt;&lt;br /&gt;In working on the problem, I decided to rewrite a bit of the code to make it more efficient. A lot of repetitive loops could be combined, and instead of parsing the name of the joint to get rid of the suffix, I could use the &lt;span style="color: rgb(255, 204, 51);"&gt;substitute&lt;/span&gt; command. In the months since I wrote the script originally, I've discovered I don't have to put `gmatch` statements into a variable, but can use them directly in "if" statements without an equal. I didn't know that before.&lt;br /&gt;&lt;br /&gt;I also made it so I don't have to select the vertices. I can select the objects or the vertices, and the script will figure it out.&lt;br /&gt;&lt;br /&gt;So I got the spur to joint script down to between 2 and 2 1/2 minutes running time from 5 minutes or more.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(102, 204, 204);"&gt;&lt;span style="color: rgb(51, 204, 255);"&gt;Cleanup and Windows&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;I wrote a cleanup utility to conform all 17 current characters to a unified naming convention. This utility forced me to learn how to manipulate GUIs in a much more coherent fashion than I'd been doing before. I needed to throw up separate analytical windows, and I didn't want them all over the place.&lt;br /&gt;&lt;br /&gt;Window # 1 has the basic controls with 5 buttons. I used the rowColumnLayout command to make the buttons span evenly across the window, two rows of two and a close button at the bottom. There's a textField to enter a character name, and all the changes executed by the script are logged in a textfile, with new entries appearing below existing ones.&lt;br /&gt;&lt;br /&gt;Window # 2 appears directly below it and the left edge lines up with the first. This window lists all the joints that are different from the standard model, so I can examine them and see if there's a misnaming, a difference in the hierarchy that shouldn't be there, or additional bones like tails, ears, ponytails, trunks, etc. I found a lot of names of objects that were out of standard that way.&lt;br /&gt;&lt;br /&gt;While Window # 2 originally was designed to be used with one character at a time, I had an occassion to check multiple characters. So I rewrote it yesterday to give me the parent transform node of each character, so I'd know which character had what problem. I'm finding I have to do this often enough that I'm going to have to write a standalone script to find the character names in the scene so I don't keep writing the same code over and over again. I can see many uses for this when I do the scene building scripts.&lt;br /&gt;&lt;br /&gt;I align the 2nd window with the first by querying the first. For example:&lt;br /&gt;window -tlc (`window -q -te "window_1"` + `window -q -h "window_1`)&lt;br /&gt;     `window -q -le "window_1"` -h 400 "window_2";&lt;br /&gt;&lt;br /&gt;And I'd do something like that for all the windows. I also have it so all the windows are minimized if the first one is minimized, and the close window closes all the diagnostic windows associated with the tool.&lt;br /&gt;&lt;br /&gt;Window_2 has text on the top, followed by a scrollLayout, followed by text, a scrollLayout and then the buttons. This is pretty handy. But it forced me to learn how to put all of this together.&lt;br /&gt;&lt;br /&gt;At the end of the script for window_2, it does a query to find out how wide the text lines are, and scales the window and scroll lists to that size. Since all of the windows next to it use a call like `window -q -w "window_2"` as part of the formula to determine their position when opened, this means that all the windows fit together like pieces of a puzzle, and self assemble even if something is moved.&lt;br /&gt;&lt;br /&gt;This all means that I am going back to my old scripts to neaten them up. If I have a row of buttons, rather than explicitly placing them with formLayout -e, I'm using automatic calculation to determine how to get the buttons exactly spaced for the width of the window or frameLayout.&lt;br /&gt;&lt;br /&gt;The way I'm accomplishing this is with a line like this:&lt;br /&gt;int $windowWidth = `window -q -w "window_2"`;&lt;br /&gt;int $offset = 3;&lt;br /&gt;int $columnSpace = 3;&lt;br /&gt;rowColumnLayout -e&lt;br /&gt; -cw 1 (($windowWidth/5)-$offset)&lt;br /&gt; -cw 2 (($windowWidth/5)-$offset)&lt;br /&gt; -cw 3 (($windowWidth/5)-$offset)&lt;br /&gt; -cw 4 (($windowWidth/5)-$offset)&lt;br /&gt; -cw 5 (($windowWidth/5)-$offset)&lt;br /&gt; -cs 1 $columnSpace&lt;br /&gt; -cs 2 $columnSpace&lt;br /&gt; -cs 3 $columnSpace&lt;br /&gt; -cs 4 $columnSpace&lt;br /&gt; -cs 5 $columnSpace &lt;br /&gt;  "buttonRCL";&lt;br /&gt;&lt;br /&gt;$offset is the amount subtracted to compensate for the scroll bar and/or frameLayout margins&lt;br /&gt;I don't subtract that from the window value directly so I can alter the widths of the columns to make the buttons as wide as they need to be to fit the text in each button.&lt;br /&gt;&lt;br /&gt;Using these techniques, if a window is resized because it's contents are wider than the initial window size, that's the value that's used to resize all the components that weren't responsible for resizing the window. It's a profound discovery for me.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 204, 255);"&gt;What Comes First, The Code or the UI?&lt;/span&gt;&lt;br /&gt;For a simple tool, it's pretty easy to just write the code. But when I need something that does a lot of complicated things, I find myself dummying up the UI first, which then tells me what I have to write into the script. What do I want the tool to do? How do I want it to work. Writing the UI first is sort of an advanced combination of an outline and flow chart. It's actually saved me a lot of time except when I have to learn new UI tricks, but I only have to learn them once. And I write them very quickly now. It also gives me a good idea of what needs to be broken into separate global procs and what can be combined into one.&lt;br /&gt;&lt;br /&gt;But I'm getting to the point where I'm starting to think about writing a UI to build UIs. There are some out there, but as usual, I like the control and know what I want.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 204, 255);"&gt;Converting Motion Data&lt;/span&gt;&lt;br /&gt;What I'm currently working on is a method for converting data on a character done before the character was all zeroed out, and when the character's primary pose was done in an "A" pose instead of a "T" pose. I've chosen to go with a "brute force" quasi-mechanical methodology over actually trying to do matrix conversions. This involves posing the old skeleton in the new skeleton's pose, creating a huge number of transforms, synchronizing one with the old skeleton, synchronizing the other with the new skeleton, parenting new to old and then synchronizing the whole thing frame by frame with the old animation. The data is then extracted from the new skeleton transforms as world space information, and transplanted either onto the skeleton itself or controls that drive the IK. A lot of flexibility can be achieved with various parenting schemes.&lt;br /&gt;&lt;br /&gt;That's the theory anyway.&lt;/variable&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19305204-114816736740410921?l=car2ns3d.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://car2ns3d.blogspot.com/feeds/114816736740410921/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19305204&amp;postID=114816736740410921' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19305204/posts/default/114816736740410921'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19305204/posts/default/114816736740410921'/><link rel='alternate' type='text/html' href='http://car2ns3d.blogspot.com/2006/05/more-tools-interfaces-and-refinements.html' title='More tools, interfaces and refinements'/><author><name>Stephen Greenberg</name><uri>http://www.blogger.com/profile/16640921787080104112</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19305204.post-114696136026843805</id><published>2006-05-06T16:46:00.000-07:00</published><updated>2006-05-06T17:32:06.510-07:00</updated><title type='text'>Scripting is like cooking...Part 1</title><content type='html'>&lt;span style="color: rgb(51, 204, 255); font-weight: bold;"&gt;I've posted out of sequence this week, since this is a two parter, and I thought Part 1 should be posted on top for more natural reading. Part 2 is below.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Before I start a big THANK YOU to &lt;a href="http://www.robthebloke.org/"&gt;Robert "Rob The Bloke" Bateman&lt;/a&gt;. He posted a reply on my &lt;a href="http://forums.cgsociety.org/showthread.php?t=352878"&gt;CG Talk Thread&lt;/a&gt; that gave me the insight to solve a major, show stopping problem.&lt;br /&gt;&lt;br /&gt;I don't think an analogy to my rapid, seat of the pants invention methodologies in the garage will be very accessible to many people. To sum it up, I need to make something that I can't readily purchase, so I scour the garage in search of discarded parts and leftover materials from other projects, and bins of fasteners, and cobble something together by using the lathe, drillpress, grinder, saws, files, oxy-acetylene torch and arc welder.&lt;br /&gt;&lt;br /&gt;But almost everyone has a refrigerator and stove.&lt;br /&gt;&lt;br /&gt;I like food to taste good, and I get easily bored. So when I need to cook something, I look in the fridge for raw materials for my project. Meats, veggies, cheese and sauces are the fundamental building blocks of all meals. I've got lots of dried spices and herbs, and will sometimes employ a canned good that has something tomatoey. Even peanut butter is useful if you want to make something with a thai peanut sauce. No cookbooks, just an idea where you grab ingredients, mix sauces together, and in the end come up with some sort of dish or sandwich that isn't boring.&lt;br /&gt;&lt;br /&gt;It's amazing what kind of variety you can get when you do that.&lt;br /&gt;&lt;br /&gt;Until this week, I never really thought much about there being a relationship between the garage mad scientist/engineer/junk-yard warrior and the cook. But it's a consistent theme: see what resources you have available, and combine them to get the result you want.&lt;br /&gt;&lt;br /&gt;What made me realize that this is a way of thinking that becomes a repeated theme no matter what you're doing, so long as you're making something, is: I realized how often I do this in scripting.&lt;br /&gt;&lt;br /&gt;I'll get to that in a minute. First, I'll revisit last week's Animation Save/Load script.&lt;br /&gt;&lt;br /&gt;It's not enough to get something working. You have to test it with the most dire conceivable scene you can find. In this case, I used our gold standard character (to which all other characters must be compared), and a 2000 frame mocap file with keys on every available channel on every joint. That's a lot of data.&lt;br /&gt;&lt;br /&gt;Well, it worked. Sorta. Turned out it would take 15 minutes to save, and 45 minutes to load. Not very feasible in production. Since I anticipate using the base functional code in a custome character/shot/scene loader with multiple characters in a scene, this speed was highly impractical.&lt;br /&gt;&lt;br /&gt;In the course of revision and restarting the interface, I had to do a lot of things repetitively. This led to refinements of the interface:&lt;br /&gt;1. The animation file is now persistent. On repeated loads, it automatically loads the last file as long as the same Maya startup is still being used.&lt;br /&gt;2. Clicking on the source, then the destination objects, and then hitting the "Map to New Character" button gets really tiresome when you have to do it 30 or more times for every animated object in the character. My first pass at resolving this led to making it a click, click and it's mapped solution: now the "Map to New Character" button was obsolete.&lt;br /&gt;3. Clicking the "Get info from File" and "Get Character Controls" buttons was getting old too, so I made those load automatically when the interface starts. Now those buttons were obsolete.&lt;br /&gt;&lt;br /&gt;So I had three obsolete buttons. And I still had to do a "click, click" for each object in the character. The couple of dozen times I had to do this, I pretty much thought the solution for the long file loads was just over the horizon. When I realized it wasn't, I created a "Save Map" and "Load Map" function in the interface. I used two of the old button positions and eliminated the third.&lt;br /&gt;&lt;br /&gt;Here's where the cooking ingredients analogy comes in. I didn't want to spend a lot of time on this stuff. So I grabbed the code from the animation save/load global procs off the shelf and added some different sauces, and now I had a "Save Map" and  "Load Map" function, with a text field with the file name. And because I solved the persistent file name problem, they'd automatically load and update the interface every time I started it.&lt;br /&gt;&lt;br /&gt;This was a huge time saver.&lt;br /&gt;&lt;br /&gt;So I was able, over repeated refinements, to speed up the code. I got it down to 10 minutes for a save, and 13 minutes for a load. Still unacceptable for production, but I was getting closer. By loading everything into an array, and working from the array, it sped things up and saved multiple iterations of code. Disabling the "undo cue" also saved a bunch of time and freed up some memory. That really adds up when you've got a 300,000 line file that you're saving/reading.&lt;br /&gt;&lt;br /&gt;But I couldn't figure out how to get the time down from that. And if I repeated the operation with the same Maya interface open, that 13 minutes would jump up to 30 minutes. And suck up a lot of memory that never came back. Something was wrong, and I was thinking about learning to use the API. But I still had to solve this problem right away, and finally posted to CG Talk about it. Prospects of solving the problem seemed dismal at first, and then Rob The Bloke came to my rescue.&lt;br /&gt;&lt;br /&gt;It turns out that printing to the script editor is unreasonably inefficient. It sucks up huge amounts of memory and time. Not really noticeable with small code, but very very noticeable with something large and highly iterative. For debugging, I had it print out the commands that were being used to set the keys on the new character. That's 300,000 lines of printing in this case. It would take up 500 megs of memory, and not give that back. Read Rob's post in the thread I posted at the top to see what he said.&lt;br /&gt;&lt;br /&gt;This was a profound insight. Deleting the print commands on both writing and reading the files sped writes to 38 seconds (also using fflush as Rob advised contributed), and reads to 2 minutes and 30 seconds or less. Despite his advice to get rid of the array, I found that it consistently knocked 10 seconds off the read time, so I went back to it. I may be revisiting this in the future for further optimization, but WHAT A DIFFERENCE!&lt;br /&gt;&lt;br /&gt;I'm now going to have to go back to all my highly iterative code that, for example, reads the data off every single vertex in a character, and eliminate the print commands for all of it. It's already made a huge difference in my "Save Weights" and "Read Weights" tools. Once a tool works and you don't have to debug anymore, get rid of the print commands!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19305204-114696136026843805?l=car2ns3d.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://car2ns3d.blogspot.com/feeds/114696136026843805/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19305204&amp;postID=114696136026843805' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19305204/posts/default/114696136026843805'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19305204/posts/default/114696136026843805'/><link rel='alternate' type='text/html' href='http://car2ns3d.blogspot.com/2006/05/scripting-is-like-cookingpart-1.html' title='Scripting is like cooking...Part 1'/><author><name>Stephen Greenberg</name><uri>http://www.blogger.com/profile/16640921787080104112</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19305204.post-114695910984311635</id><published>2006-05-06T15:49:00.000-07:00</published><updated>2006-05-06T17:26:46.120-07:00</updated><title type='text'>Scripting is like cooking...Part 2</title><content type='html'>So the second bit of this Cooking/Scripting analogy...&lt;br /&gt;&lt;br /&gt;This week I was instructed to start looking over a bunch of characters that were done before my time. What I noticed was inconsistencies in the hierarchies, a lot of transforms without children, and different naming conventions for the same joints.&lt;br /&gt;&lt;br /&gt;If I'm going to employ tools in the future that can parse and deal with the various body parts, it would sure be nice if they were always named the same thing.&lt;br /&gt;&lt;br /&gt;So I wrote a quicky tool in a few hours to deal with this. Doing it by hand was out of the question, because I had a big checklist and I was sure to miss some detail and continue propogating the problem. My current list has 17 characters, so the time to do this by hand would really add up.&lt;br /&gt;&lt;br /&gt;I settled on a "gold standard" character whose hierarchy would be used to compare all the other hierarchies.&lt;br /&gt;&lt;br /&gt;And I went to the "fridge" of previously written code to borrow code which could be redeployed in the tool. This is a real time saver, when you can look at how you handled a problem before, and not have to reinvent the wheel. I borrowed and modified parsers, cobbled quick interfaces together, pop-up windows and file writers. It does all the functions and adds them to a log file so I have a record of what was done.&lt;br /&gt;&lt;br /&gt;What I wound up with:&lt;br /&gt;1. A "promptDialog" window pops up asking me to name the character which leads all the info written to the log file.&lt;br /&gt;2. It automatically renames a bunch of standard non-conforming names of joints like the pelvis, fingers and foot parts.&lt;br /&gt;3. It deletes all transforms that have no children, but not joints, ikHandles or effectors.&lt;br /&gt;4. It pops up a scroll window that gives me a summary of what was done. If it looks like something necessary was deleted, then I'll reload the character and fix the code. So far, I haven't had this problem since the third iteration of the code.&lt;br /&gt;5. It pops up a scroll window that gives me a list on top of joints that exist in the "gold standard" character that don't exist in the character that is being fixed. On the bottom, it gives me a list of joints in the character being fixed that don't exist in the "gold standard" character. Sometimes it's because the character being fixed has joints that the "gold standard" doesn't have like a tail and ears. Or some joints are named with joints that have their lettered incrementers jumping sequence because at one point intermediate joints were removed for redundancy.&lt;br /&gt;&lt;br /&gt;But this all gives me a visual list to investigate. It alerts me to name formats that are out of conformity with the general naming convention. It points out joints that were never renamed from the default. It's a very good summary of things that might need to be looked at, and appropriately targeted.&lt;br /&gt;6. It pops up another window with a final checklist for hierarchy conformity that also includes what objects need to have "inherit transforms" turned off.&lt;br /&gt;&lt;br /&gt;When all this is done, it writes to a log file. I go and hand edit the log file with any additional steps I take with the lines of hand edited items indented, and finally, I add the file name that the newly fixed character was saved under.&lt;br /&gt;&lt;br /&gt;With this, I was able to conform 16 of the 17 characters in under 4 hours (which only took that long because I was updating the code as I found problems, and wrote a new sg_rig utility which I'll need for a different stage of zeroing rotations later).&lt;br /&gt;&lt;br /&gt;And then there's the new sg_rig utility. This pops up a summary of the rotation, rotation axis, joint orient and rotation order for specific joints I need to be certain conform to standards we need to meet. I borrowed some of the window code from the naming and hierarchy cleanup of the earlier utility script for that.&lt;br /&gt;&lt;br /&gt;I wrote the utility because, while I had the characters up, I wanted to get a preview of the work I had ahead of me and to anticipate some upcoming problems I see with correcting them. I'll have my work cut out for me next week. I'm getting some ideas for maybe logging old data and correcting animation files being loaded from earlier work based on that old data (just in case dealing with this becomes &lt;span style="font-style: italic;"&gt;my problem&lt;/span&gt;).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19305204-114695910984311635?l=car2ns3d.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://car2ns3d.blogspot.com/feeds/114695910984311635/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19305204&amp;postID=114695910984311635' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19305204/posts/default/114695910984311635'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19305204/posts/default/114695910984311635'/><link rel='alternate' type='text/html' href='http://car2ns3d.blogspot.com/2006/05/scripting-is-like-cookingpart-2.html' title='Scripting is like cooking...Part 2'/><author><name>Stephen Greenberg</name><uri>http://www.blogger.com/profile/16640921787080104112</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19305204.post-114634271404916021</id><published>2006-04-29T12:05:00.000-07:00</published><updated>2006-04-29T13:31:54.383-07:00</updated><title type='text'>This is how it turned out...</title><content type='html'>&lt;div style="text-align: center;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="text-decoration: underline;"&gt;&lt;/span&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/3866/1908/1600/animRWinterface01.0.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://photos1.blogger.com/blogger/3866/1908/320/animRWinterface01.0.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;So this is how it turned out. It has common wildcards for control names, a textfield to enter combinations of control names or animated objects which may not be controls. The list will only show objects which have animated attributes. If "none" is selected, all the animated objects in the scene will be listed.&lt;br /&gt;&lt;br /&gt;For saving animation, the saver will by default save the animation for everything in the list. If you select objects from the list, it will save animation only from those objects, and only on channels that are animated.&lt;br /&gt;&lt;br /&gt;There is an option to save animation only from the selected referenced character, so if there are multiple characters in a scene, only the selected reference gets saved. This is currently only a single selection option, but if there's a need, I can make it multiple selection.&lt;br /&gt;&lt;br /&gt;I've added an "Animation Offset" option, which allows animation that may not start until the middle of the scene to be synchronized with the scene on load, and a "Motion Capture" option for saving, which makes for file sizes that are 25% or less the size of the full animation file which has weight and tangent information.&lt;br /&gt;&lt;br /&gt;I also added a "No Character Reference" mode, so that animation can be transferred to and from characters which are not referenced, as many files coming to me through motion builder haven't been referenced yet. When "No Character Reference" is checked, the text that says "Reference Character Controls" changes to "Character Controls".&lt;br /&gt;&lt;br /&gt;The remapper automatically loads the available animated channels from the file on read into the left hand column below in the "Anim File Controls" column, and selecting a character from the "Reference List" above automatically loads its available objects based on the "Select Wildcard" choices at the top of the interface (including the wildcards entered into the text field).&lt;br /&gt;&lt;br /&gt;I've also made the selection process much faster. A single click on either of the objects in the "Anim File Controls" or "Reference Character Controls" text boxes will add the from =&gt; to mapping to the Animation File =&gt; Character text box. The Animation File =&gt; Character display is self correcting, so if you make a mistake and change the object mapping to the "Reference Character Controls" object, it will replace the map you previously entered with the updated one.&lt;br /&gt;&lt;br /&gt;I've left all the manual buttons for conveying data in the interface like "Get Info from File" ,  "Get Character Controls" and "Map to New Character" even though I've added more automation for those features so they generally aren't necessary. If all the automated stuff continues to work under production use, then I might take the buttons out.&lt;br /&gt;&lt;br /&gt;Reading mapped files is a "What you see is what you get" process, since the information is actually taken from the  "Animation File =&gt; Character" text box, and not the variables used to create the box.&lt;br /&gt;&lt;br /&gt;Making everything in these text boxes update automatically when options were changed turned out to be more challenging than I thought. It's still not perfect, and sometimes to get the "Character List" (at the top) to update with the proper amount of rows, I have to turn "Show Objects Selected With Wildcard" checkbox on and off.&lt;br /&gt;&lt;br /&gt;Another challenge was getting a perfect match on tangents and weights on curves. It turned out that if the animation had options like "Weighted Tangents" or "Lock Tangent Weights" turned on or off, I'd get incorrect information in the saved file. It was solved by caching the current state of the tangents and weights, turning weighted tangents on, unlocking tangent weights, breaking the tangents, saving the information, and then turning them back on with the cached state. All of that information is saved unless the "Motion Capture" checkbox is checked, in which case no tangent information is saved (everything is assumed to be linear since there's a key on every frame), and no "infinity" information is saved ("infinity" is assumed to be constant).&lt;br /&gt;&lt;br /&gt;I'm using my own file format rather than an existing one. It doesn't seem like there's a truly universal animation file format being used, and I can add to this one or subtract from it at will based on the needs of the production. I've already had to add additional variables for accurate tangent weight replication. Since the format easy to parse out, it can be translated to anything else that's ASCII based with pretty little effort, though the translation can be time consuming if a lot of recursion is needed. The downside is that the files can be huge, but they &lt;span style="font-style: italic;"&gt;are &lt;/span&gt;"human readable".&lt;br /&gt;&lt;br /&gt;The "Name" basis of this file format makes it particularly suited to production, since hierarchies can change during production, particularly the number of children of a particular hierarchy, which I've found throws things off a great deal and can make old animation incompatible with new animation. The remapping feature seems to be a pretty obvious need, and it's amazing that it's not something that's become a standard feature set in Maya.&lt;br /&gt;&lt;br /&gt;I would really like to resolve a memory issue with using the animation file loader, particularly with motion capture files, which have a huge amount of data. During loading, it will suck up a ton of memory, even sending my machine into "swap" virtual memory space. And it doesn't give it back when the process is finished. The only solution I have right now is to save the scene, kill Maya and then restart Maya. If anyone has any solutions to this problem, I'd love to hear them.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic; font-weight: bold;"&gt;Plans for the future:&lt;/span&gt;&lt;span style="font-weight: bold;"&gt; &lt;/span&gt;&lt;br /&gt;The underlying code can be used for scene loading, bypassing the reference process in Maya if it becomes necessary, providing the code proves to be reliable enough and I resolve the annoying memory issues. If there's a use for it, I can use a "Save by timeline" feature, and maybe a "hide until first frame" feature for characters that have no animation until the middle of a shot.&lt;br /&gt;&lt;br /&gt;I may also add an "animation copy" feature, to copy animation between two characters loaded at the same time, possibly deploying the techniques I'm using in another tool that turns hierarchical straight FK rotation keys into IK translational keys between dissimilarly proportioned characters.&lt;br /&gt;&lt;br /&gt;If it can be made more efficient, I might make a multi-select reference mode that can load the same animation on multiple characters for crowd scenes, with a random range of time offset to the characters aren't all moving at the same time. I've thought of ways to also randomize initial character placement so the characters are at a fixed proximity to the other characters, but it would be hard to duplicate some of the features I've heard about in Massive. Also, I'd have to work on my use of matrices to determine location within a bound distance.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19305204-114634271404916021?l=car2ns3d.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://car2ns3d.blogspot.com/feeds/114634271404916021/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19305204&amp;postID=114634271404916021' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19305204/posts/default/114634271404916021'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19305204/posts/default/114634271404916021'/><link rel='alternate' type='text/html' href='http://car2ns3d.blogspot.com/2006/04/this-is-how-it-turned-out.html' title='This is how it turned out...'/><author><name>Stephen Greenberg</name><uri>http://www.blogger.com/profile/16640921787080104112</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19305204.post-114589649072217969</id><published>2006-04-24T09:13:00.000-07:00</published><updated>2006-04-24T13:02:49.466-07:00</updated><title type='text'>A little something I'm working on</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/3866/1908/1600/animRWinterface.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://photos1.blogger.com/blogger/3866/1908/320/animRWinterface.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;This is the start of an interface for animation tools I'm coming up with. It allows animators to save in a format I came up with that is entirely name based, and allows remapping to characters that are dissimilarly named.&lt;br /&gt;&lt;br /&gt;The advantage of using a custom animation file format is that I can add features to it as needed and put parsing hooks in that lower the coding time.&lt;br /&gt;&lt;br /&gt;I've already thought of a lot of features to add to this interface, including attribute break downs, detection of missing attributes and an ability to add them or skip them, and various failure and recovery modes.&lt;br /&gt;&lt;br /&gt;I've also thought about ways to write a remap into the referenced character file so this doesn't have to be repeated if the remapping is something that's done repeatedly.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19305204-114589649072217969?l=car2ns3d.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://car2ns3d.blogspot.com/feeds/114589649072217969/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19305204&amp;postID=114589649072217969' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19305204/posts/default/114589649072217969'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19305204/posts/default/114589649072217969'/><link rel='alternate' type='text/html' href='http://car2ns3d.blogspot.com/2006/04/little-something-im-working-on.html' title='A little something I&apos;m working on'/><author><name>Stephen Greenberg</name><uri>http://www.blogger.com/profile/16640921787080104112</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19305204.post-114453348829076643</id><published>2006-04-08T13:30:00.000-07:00</published><updated>2006-04-08T15:24:08.950-07:00</updated><title type='text'>Bet you thought I'd never update this thing</title><content type='html'>So I got a job as a character rigger at Threshold Animation Studios. It turns out everything I learned along the way has come in handy.&lt;br /&gt;&lt;br /&gt;I walked in with a suite of rigging tools I created. This turned out to be a real good thing. The first thing I had to do was mod them to conform to the in-house naming conventions. This would have been harder using  downloadable rigging tools, since most of them have multiple library calls and tracking down the naming conventions in all the disparate global procs would have been daunting.&lt;br /&gt;&lt;br /&gt;The other thing, is that the studio has special requirements which required serious modifications to the functionality of the rigging scripts.&lt;br /&gt;&lt;br /&gt;If you look at http://casadiablos.com/steph/stephInterfaces.htm, you can see the base interfaces I use in my tool kit. I've added a spur builder, which creates customized bone spurs to tailor autoskinning. I can interactively resize them to fit the character, then move them around to where the autoskinning needs the greatest influence from the parent bone.&lt;br /&gt;&lt;br /&gt;The other advantages to having a whole suite of tools, is naming conformity. This makes it easier to have all other tools act on the given objects. In the case of the spurs, it's [bone name]_A(B,C,D,etc)_SPUR.&lt;br /&gt;&lt;br /&gt;I wrote a script that takes the skin assignments for every vertex and CV, and writes them to a file. All of them. For every object. This kind of duplicates the functionality of skin maps, but at the same time, it's a one stop process. Not a bunch of individual files for each object. I had to create my own file format for that.&lt;br /&gt;&lt;br /&gt;This was a fortuitous development, because the character models are frequently revised. If the modifications are minor, like character proportions, with no added vertices/CVs, then I just save out the weights on the old character, reposition the skeleton and reload the file. Voila!&lt;br /&gt;&lt;br /&gt;While objects that are modified severely or have new vertices added can't necessarily use the old weight assignments, often it's only part of the character that's been modded, and I can go back to the spurred version of the character before the skin weighting spurs were removed, and reassign that part of the character.&lt;br /&gt;&lt;br /&gt;Another handy tool I developed allows me to de-assign unwanted weights. You don't want the abdomen to deform when you move the arm. I have a checkbox arrangement for the common bones, and a text entry field for bones added later. These bones include all the child spurs.&lt;br /&gt;&lt;br /&gt;I updated sg_syncOb. I haven't uploaded it yet, since it uses the house naming convention and is proprietary at this time. But it now includes a zooty arrow-ball as a controller type. When it's fully updated, it will also offer the option of creating a joint with selectable shapes to select that joint as a controller. This had the advantage of being able to use the jointOrient attribute for externally rotating the controller, such as using the forearm to rotate an IK control foreward kinematically, while still being able to animate that controller's rotation on top of it. Very useful, but it's tricky to get working and not without it's pathologies.&lt;br /&gt;&lt;br /&gt;So here are the features of the rigging suite:&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 204, 255);"&gt;Skeleton&lt;/span&gt;&lt;span style="color: rgb(51, 204, 255);"&gt;:&lt;/span&gt; creates guide spheres that are interactively scaleable to get close to the character's proportions, and creates a base FK skeleton conforming to the house naming convention. Options are selectable number of fingers, and number of bones in the fingers, back, head, neck, arms and legs. The code is there for tail, ears and pony tail, but I haven't connected it to the interface. There's also a checkbox to turn axes on and off for the entire skeleton interactively. The guide sphere portion has a mirror function so I only have to align half the spheres in the appendages. All numeric options for number of bones and scaling of the guide spheres use sliders but numbers can be manually entered as well.&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 204, 255);"&gt;Make Control Objects: &lt;/span&gt;This just brings up the latest revision of syncOb.&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 204, 255);"&gt;Create Spurs:&lt;/span&gt;&lt;span style="color: rgb(51, 204, 255);"&gt; &lt;/span&gt;This makes the bone spurs for skinning. It arranges the bones in a circle around the parent bone, and names them as mentioned above. There's a selectable number of bones, the axis of the bone to arrange them in a circle, and interactive radius adjustment. The interactive radius can be used by selecting the parent bone at a later time and using the slider as well. Buttons are "Create Spurs", "Spur to Joint" (which takes all the spur assignments and adds them to the parent bone), and "Delete Spurs" (which deletes the no-longer needed spurs after using "Spur to Joint").&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 204, 255);"&gt;Rename Skeleton and Control Objects:&lt;/span&gt; This allows me to create joints by hand, say additional spurs going in a non-circular orientation, and then rename them to conform to the naming convention. The text fields include "Jointname", starting letter, and suffix (JNT, CTL, etc). Works on any number of selected object and indexes them with increasing alphabetical representation (B, C, D, etc).&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 204, 255);"&gt;Remove Unwanted Weights:&lt;/span&gt; As mentioned above, this removes weight influences from bones that you don't want influencing that section of the character. There are checkboxes for non-left-right bones, and individual checkboxes for the left and right appendages so I can remove the influences from autoskinning like the left femur, tibia, and foot bones from influencing the right. There's also the aformentioned text field for entering bone names not represented by a check box. Buttons are "Delete Weights" and "Clear Check Boxes" (which also clears the text field).&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 204, 255);"&gt;Save/Read Weights: &lt;/span&gt;This has a filename field that you can manually type, as well as buttons that call up a file requester to set your directory path and name for the file. I have a filetype I created, and the suffix is automatically added. There's a "Get" button to get the file with the same type of requester. Unfortunately, I couldn't customize the default filetype, so you have to enter *.weight (that's not the actual suffix name) to see the .weight files. Buttons are "Save Weights", "Delete Existing Weights" (removes all current skin assignments, required to read the file or it will error on read if it doesn't double assign, a bad thing), "Read/Reset Weights" (which will delete and read the weights), and "Read Weights Only".&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="color: rgb(51, 204, 255);"&gt;Make Chain Stretchy:&lt;/span&gt; &lt;/span&gt;This allows me to select the start joint and end joint for a stretchy chain, using either RP (standard IK) or SplineIK. It also strictly names (with the joint base names) all the various nodes it takes to make a stretchy chain so they can be easily identified when manually editing the conditional, multiply/divide, distance and curveInfo nodes. Radio buttons for the axes select the the axes along the joint that are scaled by the stretchy command. There are also radio buttons for RP and Spline construction, and an option to create a stretchy single bone.&lt;br /&gt;&lt;br /&gt;I'm also working on a conversion utility to take the "animation" information off of a skeleton with House of Moves channel data brought in to Maya through the FBX importer, and convert that to combined rotational and positional data to drive an advanced IK rig for hand keying over motion capture without a slow, double rig being needed (the way you can do it in Motion Builder). The tool also takes frames numbered using a time code scheme and puts them at frame 1. I'll add a feature to the interface that lets you set the start frame at an arbitrary number. This also allows for importation of the data onto reskinned characters, and I'll probably figure out a way to allow the data to be put onto non proportionally similar characters for crowd scenes.&lt;br /&gt;&lt;br /&gt;A parallel project of mine is an addition to the autorigger that sets up all of the controls automatically (usually a standard feature of autoriggers), with the addition of a double hierarchy so the mocap data can be imported, but you can animate using stretchy IK on top of that. I'm dubious about the ability of this system to use space switching techniques because of the underlying motion capture data, but we'll see. As far as I can plan, if there is space switching, it has to be done before the mocap data is applied. This represents a similar problem for foot axis pivot switching.&lt;br /&gt;&lt;br /&gt;I've started learning about dynamics. My initial impression is that to get the results you want for complex limbs and such, it takes so much tweaking that it would just be faster to hand animate it. But we'll see where I can make it useful.&lt;br /&gt;&lt;br /&gt;At this time, I'm not going to be doing tutorials. I don't really have the time, and I'd really rather wait until my tools and techniques have been battle tested a bit more.&lt;br /&gt;&lt;br /&gt;Thanks for reading. Hopefully I'll have a chance to update this a little more often.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19305204-114453348829076643?l=car2ns3d.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://car2ns3d.blogspot.com/feeds/114453348829076643/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19305204&amp;postID=114453348829076643' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19305204/posts/default/114453348829076643'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19305204/posts/default/114453348829076643'/><link rel='alternate' type='text/html' href='http://car2ns3d.blogspot.com/2006/04/bet-you-thought-id-never-update-this.html' title='Bet you thought I&apos;d never update this thing'/><author><name>Stephen Greenberg</name><uri>http://www.blogger.com/profile/16640921787080104112</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19305204.post-113686922870729317</id><published>2006-01-09T20:44:00.000-08:00</published><updated>2006-01-10T12:56:33.823-08:00</updated><title type='text'>Skin weights and the rig demo</title><content type='html'>So I spent a week figuring out my skinning script. I think I've finally found a reliable way to end the skinning drudgery. Or at least I have another tool on my toolbelt to deal with it. That tool belt is getting heavy enough to drag my pants down and give me "plumber's cleavage". And I look at the tools in the rigging hardware store, and know I haven't even started.&lt;br /&gt;&lt;br /&gt;The script took 426 lines. Not a huge amount, but still a pretty good sized effort. The script is somewhat slow, but considering the overall time it saves, waiting 15 minutes or so isn't so bad. Actually, on this model it's a lot faster. This weeks secret weapon: the "eval" command.&lt;br /&gt;&lt;br /&gt;A big "shout out" to Mike Hovland for setting me on the right path.&lt;br /&gt;&lt;br /&gt;Last week I did my rig demo. It seems to be going over well on CG Talk. I can see light at the end of the tunnel.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19305204-113686922870729317?l=car2ns3d.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://car2ns3d.blogspot.com/feeds/113686922870729317/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19305204&amp;postID=113686922870729317' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19305204/posts/default/113686922870729317'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19305204/posts/default/113686922870729317'/><link rel='alternate' type='text/html' href='http://car2ns3d.blogspot.com/2006/01/skin-weights-and-rig-demo.html' title='Skin weights and the rig demo'/><author><name>Stephen Greenberg</name><uri>http://www.blogger.com/profile/16640921787080104112</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19305204.post-113556666607955095</id><published>2005-12-25T17:17:00.000-08:00</published><updated>2005-12-25T19:11:06.183-08:00</updated><title type='text'>Finishing the prototype</title><content type='html'>I think the prototype rig is done. In the last week, I've added a pseudo forward kinematic style forearm orientation to my hand control. As well as getting a true FK arm working, with synchronization to the IK arm after switching, and vice versa.&lt;br /&gt;&lt;br /&gt;The forearm orientation works especially well. I've gotten it optimized and working without an expression. This means the hand controller rotates with forearm, and the rotation channels are completely relative. So if you rotate the arm in IK or FK 90 degrees, but haven't rotated the hand, the hand rotates that same 90 degrees but the channels stay at 0 0 0. Based on the comments at Jason Schleifer's web site, a lot of people have not had any luck accomplishing this.&lt;br /&gt;&lt;br /&gt;Keeping to my rigging philosophy of being able to alter the rig midstream in a shot and animating that alteration, I've added synchronization of the forearm follow and isolation settings so there's no jumping between states.&lt;br /&gt;&lt;br /&gt;At first I borrowed &lt;a href="http://dpk.stargrav.com/"&gt;Daniel PK&lt;/a&gt;'s solution, which required an expression. But using part of his methodology, I was able to make an optimized direct connection instead.&lt;br /&gt;&lt;br /&gt;The only limitation I'll state on the FK arm, is that stretchy doesn't work in FK...it snaps to an unstretched state if you had the arm stretched out. Also, you can't switch from bending the elbow backwards (as in "successive breaking of the joints") in FK, to IK without some unfortunate side effects. IK just doesn't support backward bending on the elbow. I could make a pseudo IK controller that would enable such things, but I think the arms already have enough choices for animators as it is, with IK/FK, FK rotation on IK hand, and six animatable and synchronized space switching choices, plus isolated shoulder rotation on both FK and IK.&lt;br /&gt;&lt;br /&gt;I did a chopped up, lo res version of the character, which can be interactively switched (even animated between resolutions). Amazing as it seems to me, I had to actually write my own tool to chop the character up into separate objects to parent the segments directly to the bones. I posted this up at HighEnd3D (&lt;a href="http://www.highend3d.com/f/3896.html"&gt;sg_polySeparateObject.mel&lt;/a&gt;). Really simple script, and amazing that this function isn't built into Maya.&lt;br /&gt;&lt;br /&gt;In addition to the arm controls, I also completely altered the way the eye control works after input from Jeff Cooperman. It is now a rotational control, with an isolated option to aim at a control target, which itself can be constrained. Unconstrained, the eye position is synchronized between the isolated and rotational controls. Also added an eyelid shape control.&lt;br /&gt;&lt;br /&gt;I optimized the rig speed Saturday, and saw a 6-8x increase in speed. It's now totally realtime in interaction, and tests so far play at full 24fps speeds.&lt;br /&gt;&lt;br /&gt;I should begin working on a rigging demo Tuesday.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Planned Improvements:&lt;/span&gt;&lt;br /&gt;Character interface&lt;br /&gt;Ground-up skeleton rebuild with new tools.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Scripts&lt;/span&gt;&lt;br /&gt;Besides the polySeparateObject script, I'm starting work on my skinning script. This will be used with my rigging tools. The rigging tools will create spokes eminating from the main bones, which can be user adjusted, to improve precision of proximity assignment. In the prototype this has worked well.&lt;br /&gt;&lt;br /&gt;To facilitate reasonable rig speed, I'm working on a script to take assignments made to the so called "SPUR" bones, and add them to the parent bone, thus boiling out a great deal of soft skin cluster assignment that slows the rig noticably. This is an ambitious script, and the technique will significantly reduce the need to "paint" weights.&lt;br /&gt;&lt;br /&gt;The challenge in this will be how to manage keeping SPURs that can be used for FFDs and pseudo muscle controls.&lt;br /&gt;&lt;br /&gt;I've already gotten the portion of the script which allows me to read which vertices are assigned to what bones, and at what weights. I'll need to parse these, transfer and or add these values to the parent bone. Much of the code for parsing exists in &lt;a href="http://www.highend3d.com/maya/downloads/mel_scripts/character/3870.html"&gt;syncOb.mel&lt;/a&gt;.   Thanks go to Mike Hovland for pointing me in the right direction for locating the weights on the vertices/CVs.&lt;br /&gt;&lt;br /&gt;I'm not including the various character specific scripts for synchronizing switching on the head, eyes, hands, shoulders and feet. Or the obsolete script for IK hand pseudo FK.&lt;br /&gt;&lt;br /&gt;This week I should start working on graphic interfaces.&lt;br /&gt;&lt;a href="http://www.highend3d.com/maya/downloads/mel_scripts/character/3870.html"&gt; &lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19305204-113556666607955095?l=car2ns3d.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://car2ns3d.blogspot.com/feeds/113556666607955095/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19305204&amp;postID=113556666607955095' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19305204/posts/default/113556666607955095'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19305204/posts/default/113556666607955095'/><link rel='alternate' type='text/html' href='http://car2ns3d.blogspot.com/2005/12/finishing-prototype.html' title='Finishing the prototype'/><author><name>Stephen Greenberg</name><uri>http://www.blogger.com/profile/16640921787080104112</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19305204.post-113436892944472316</id><published>2005-12-11T21:35:00.000-08:00</published><updated>2005-12-11T22:28:49.506-08:00</updated><title type='text'>Space Switching Madness</title><content type='html'>It seems that there are always unwritten, esoteric rules to Maya commands.&lt;br /&gt;&lt;br /&gt;After my success with the space switching capabilities on the hands, I decided to add synchronizing scripts to the feet, tail and head, so when switching to isolation modes in those, they wouldn't jump. Or in the case of the feet, going from complete isolation to moving with the body.&lt;br /&gt;&lt;br /&gt;Now, the isolation mechanism is similar, but sufficiently different on each of these, that I had some difficulty with every single one. That's because "xform -q -ws -a -t " doesn't actually give you the value you think you should be getting. If you read the docs, and just about everything out there on the command, you should be getting a full, world value for the location of the object, regardless of what's going on in the hierarchy above that object.&lt;br /&gt;&lt;br /&gt;No dice. This is a horribly behaved command when, it turns out, the objects in the hierarchy above the one you seek a value on, have their transforms zeroed out. Especially if the object you're trying to get the information on also has the transforms zeroed.&lt;br /&gt;&lt;br /&gt;But there's more. If the object you're trying to get information on is &lt;span style="font-style: italic;"&gt;not&lt;/span&gt; zeroed, it won't work right either when you try to put the xform you were caching, back onto the the object so it doesn't move when you throw the switch.&lt;br /&gt;&lt;br /&gt;Like everything else, things get easy once you know what you're doing. It took hours of detective work to figure out what was different between the head and the feet and the arms. Turned out, it was having a zeroed out parent. I arrived at this conclusion after trying every "xform" flag permutation. Absolutely nothing other than "-rp" would return a reasonable value. And "-rp" is useless if you want to transform the whole object. So I manually cut and pasted the values derived, and found the values were relative to the parent object's zeroed out transforms. Even though I demanded "world space" values with the "-ws" flag. Go figure.&lt;br /&gt;&lt;br /&gt;So after hours of noodling with this, I completely reset the parent object to no offsets. The value in the translation box would be the exact ones that would come up on a "-rp" query.&lt;br /&gt;&lt;br /&gt;And what do you know? With a real world value for the parent object, suddenly the script worked the way it was supposed to. The transforms were read, cached, and dumped back into the head, and the head didn't jump when the isolation mode changed. Amazing. Hopefully things will go smoother with my last two isolation controls tomorrow, on the clavicle.&lt;br /&gt;&lt;br /&gt;It took awhile to find the pattern that had made things (IMO, unnecessarily) difficult, and turned each attempt at a self compensating space switching control into a cloak and dagger, sleuthing ordeal. And I don't think I've got all the answers. The clavicle controls are nested deep in a complex hierarchy, and I'm expecting to run into additional "gotchas" that may require some complicated vector math to solve. Or maybe the rigging gods will smile kindly on me, and things will work predictably instead of idiosyncratically.&lt;br /&gt;&lt;br /&gt;The most amazing thing about this was that not one person I talked to on the Internet knew this. Usually you use "xform" for moving stuff like particles around a scene, or relating objects to other objects at the same hierarchy level, I suppose. At least, based on the tutes and books I have, that seems to be the case. It appears that I'm using this command to do something for which it was not intended.&lt;br /&gt;&lt;br /&gt;But there's really good news. In getting this to work properly now, I've eliminated the "autokey" problem entirely. I no longer get keys arbitrarily added when scrubbing or paging frame to frame. I've also eliminated delays that occurred with the prior scripts which used locators and constraints to synchronize the elements. The "attribute" change is no longer detected at unwanted times, and objects no longer select and deselect themselves.&lt;br /&gt;&lt;br /&gt;I'll have to ask some riggers if running all these scriptJobs has some drawback I don't know about. I'm sure it's wasting cycle time, but I haven't detected an overhead hit with the increased number of scripts. I've also combined them all into one "uber script" so I can easily change the object names when Maya adds the "namespace" prefix to everything when referencing. It's all good so far.&lt;br /&gt;&lt;br /&gt;So now, I have a head isolation control that not only compensates for rotation, but if I translate the head for some reason, it still works. The feet work stunningly well, and I can see using this a lot more than I thought I would, especially for the walk I have in mind for KrazyCat, where he does a lot of swiveling with his foot out. In playing with the hands, I've found that the space switching is useful for something I hadn't anticipated: smoothing out bumps in arcs that occur from higher hierarchical movement. I can go to world space for a few frames, then switch to hierarchical mode, and now I have a compensated arc that works beautifully. I wish I had this tool on &lt;span style="font-style: italic;"&gt;Tripping the Rift&lt;/span&gt;. I don't know how the tail is going to work yet, but I found that on the turnaround test, a little isolation at the beginning of the turn really alleviated the need to manually counteranimate (well, it was counteranimating itself really). So far, I'm really pleased with the way this is working.&lt;br /&gt;&lt;br /&gt;Speaking of the tail, I'm going to have to re-do the architecture on it. More bones and probably a slightly different hierarchy.&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-style: italic;"&gt;&lt;span style="font-style: italic;"&gt;&lt;span style="font-style: italic;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;Scripts&lt;br /&gt;&lt;/span&gt;leftHandSwitch&lt;br /&gt;rightHandSwitch - both of these are the finished space switching scripts&lt;br /&gt;HandSelect - This selects both the hand control and the rotate x control I added to eliminate gimbal lock.&lt;br /&gt;handSwitchOn - This was the script I used to lock out channels so they wouldn't automatically add undesired keys. However, now it's no longer needed.&lt;br /&gt;lFootSync&lt;br /&gt;rFootSync - These are the scripts that stop the feet from jumping when I switch from world space to body space.&lt;br /&gt;tailSync - The script that stops the tail from jumping when switching from hierarchical to isolated modes.&lt;br /&gt;headSync - The script that stops the head from jumping when switching from hierarchical rotation to isolated rotation.&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Planned improvements:&lt;br /&gt;&lt;/span&gt;I need to clean up the scripts to eliminate all the commented out features that are no longer used or needed, and delete scripts that aren't being used anymore, as well as their related, commented out, scriptJobs.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-style: italic;"&gt;&lt;span style="font-style: italic;"&gt;&lt;span style="font-style: italic;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19305204-113436892944472316?l=car2ns3d.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://car2ns3d.blogspot.com/feeds/113436892944472316/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19305204&amp;postID=113436892944472316' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19305204/posts/default/113436892944472316'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19305204/posts/default/113436892944472316'/><link rel='alternate' type='text/html' href='http://car2ns3d.blogspot.com/2005/12/space-switching-madness.html' title='Space Switching Madness'/><author><name>Stephen Greenberg</name><uri>http://www.blogger.com/profile/16640921787080104112</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19305204.post-113411135557252624</id><published>2005-12-08T21:07:00.000-08:00</published><updated>2005-12-08T22:55:55.606-08:00</updated><title type='text'>Space Switching, animating topology, and eliminating gimbal lock</title><content type='html'>Among the features I've been trying to solve, space switching on the hands has been a big one.&lt;br /&gt;&lt;br /&gt;What I wanted to end up with was a pulldown menu on the hand control that would let you switch seamlessly from the hand being parented to the clavicle, upper torso, hip, head and thigh. Without jumping position when the switch is thrown.&lt;br /&gt;&lt;br /&gt;I'd planned to use the xform command. And I did to some extent. But I found using an interim object as a position marker (via my align script integrated into an expression in a scriptJob) and then realigning to it was a bit more reliable. I found that for xform to work, I had to run the same line twice. The first time would throw the hand off in space, and the second would do what it was supposed to. I'll probably revisit removing the interim synchronizer later, but it's working now.&lt;br /&gt;&lt;br /&gt;For some reason, everything works perfectly with the autokeyer off. But when it's on, and you scrub, it sometimes drops a key when you stop scrubbing. On both hands, not just the one you have selected. Where the scriptJob should be actuating the expression only when the attribute is changed, as the flag suggests, it seems to detect the changed attribute that's been keyed.&lt;br /&gt;&lt;br /&gt;I also found that using the script "live" was unreliable. That is, relying on the script to flip the switch as you went forward or backward isn't fast enough because of the order in which Maya evaluates nodes. So I added channels to the hand that reflect the channels on the parent constraint underlying this whole technique. Set those at the same time the other channels on the hand are set, and it's flawless. With the channels on the hand control itself, connected to the channels on the constraints, an animator can move keys around in the dope sheet without having to worry about channels on some remote object screwing them up.&lt;br /&gt;&lt;br /&gt;So now I can animate, and if I want to rest a hand on the hip, I just pulldown "hip" on the "Wrist Parent" channel, and the hand stays on the hip. If the character wants to put his head in his hands and have the hands stick while shaking his head in woe, just pulldown the "head" option. If the character is leading the hand action by moving his shoulder first and you want the hand to follow a couple of frames later, just switch the Wrist Parent to "UpTorso". The other two options are "Thigh" and "World".  "World" just does what people usually do with IK hands. The hands just sit in space, waiting for you to move them. The cool thing about this as a simple pull down option, is that when you get that bump from some combination of body moves, but you want to maintain a smooth arc for a few frames, it's just a quick switch away. Switching back with perfectly synchronized hand movement is simple and more important...fast.&lt;br /&gt;&lt;br /&gt;This took two days to come up with. There are a lot of logical things that just don't work in Maya, or at least not the way you'd think they would. Of course, now that I know what works, it won't take as long next time ;)&lt;br /&gt;&lt;br /&gt;Next up, was finishing off a simple topology control on the head. Basically just two controls on the side of the head that let you pull the upper face of this character like taffy, just as the control on top of the head pulls the top of the head like taffy.&lt;br /&gt;&lt;br /&gt;Added rudimentary whisker controls.&lt;br /&gt;&lt;br /&gt;Also added, anti-gimbal locking for the hands. First hand control operates Y and Z rotations only, second control handles x rotation only. ScriptJob to actuate automatic selection of both objects at the same time (something I've found quite useful, as used on the ear controls as well). I added a channel to display the X rotation of the gimbal control, but numeric input must be done in the non animatable X channel of first control. The rotation gizmo functions as you'd expect in "gimbal" mode. Only all the X rotation is being done on a completely separate object.&lt;br /&gt;&lt;br /&gt;I wish I could make this a little more transparent. Like substituting the "Rotate X" channel for the one on the gimbal x rotate controller. But no dice, at least not yet if at all. At this point the compromise of functionality over transparent elegance will have to be sufficient.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Scripts&lt;/span&gt;&lt;br /&gt;I put up my first script on HighEnd3D. sg_syncOb. This is a script I use a lot for making control objects, or just objects that automatically name themselves and locate themselves where a previously picked object is. No nifty GUI, which disappoints some people, but very powerful. Works with multiple selections, a lot of options, including color selection. Makes objects that are non-shading and non rendering. Can parent or constrain the original objects to the new ones. Or not. Automatically picks up the name, parses out mid name object type, and substitutes it for one that is user assigned. The naming scheme should be useful in other scripts.&lt;br /&gt;&lt;br /&gt;I commented the script so others who use the script can part it out and add new features or functions. Also, so I could remember what I was thinking when I wrote it.&lt;br /&gt;&lt;br /&gt;I'm writing scripts now trivially for searching and getting results line by line so I can paste things into a script faster, sometimes for quickly connecting large numbers of attributes. I've refined script testing so there's less trial and error, or at least the trial and error cycle is faster.  Looks like I'll have to come up with my own attribute reorganizing script, because attributeMan.mel didn' t want to work on the hands. Or it would only work on one of the attributes and I couldn't move the new attributes further up the line. So I had to manually reorganize them.&lt;br /&gt;&lt;br /&gt;A task for another day.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19305204-113411135557252624?l=car2ns3d.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://car2ns3d.blogspot.com/feeds/113411135557252624/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19305204&amp;postID=113411135557252624' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19305204/posts/default/113411135557252624'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19305204/posts/default/113411135557252624'/><link rel='alternate' type='text/html' href='http://car2ns3d.blogspot.com/2005/12/space-switching-animating-topology-and.html' title='Space Switching, animating topology, and eliminating gimbal lock'/><author><name>Stephen Greenberg</name><uri>http://www.blogger.com/profile/16640921787080104112</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19305204.post-113359891476609639</id><published>2005-12-02T23:38:00.000-08:00</published><updated>2005-12-03T00:35:14.793-08:00</updated><title type='text'>Scripts with flags</title><content type='html'>I've been busy for the last couple of days and haven't done any new rigging. But I've been putting a couple of hours here and there to address some script inefficiency and figure out some vital scripting tricks.&lt;br /&gt;&lt;br /&gt;This has been bothering me for a few days, and I finally decided to do something about it.&lt;br /&gt;&lt;br /&gt;Up to now, I've had a bunch of separate scripts with similar functionality. It goes something like this: make a locator, align the locator, constrain the object it was aligned to, to the new locator. Or a non-shading, non-rendering sphere. Or parent instead of constrain. Or align the point only. I just modified the script and saved it as a different script for each purpose.&lt;br /&gt;&lt;br /&gt;This seemed inefficient. Especially at 2am, when I couldn't remember which script did what.&lt;br /&gt;&lt;br /&gt;So I decided to start merging all these scripts into one uber script, and add some options along the way. Now, when I type the script name, a dialog box pops up, which lists all the flags, including the choice between sphere and locator, and I'll add  poly cube, circles and squares (and maybe some other things as well) on Monday. Maybe I'll add color choice too.&lt;br /&gt;&lt;br /&gt;Nice thing about this is that at 2am, I won't have to remember the flags either.&lt;br /&gt;&lt;br /&gt;I've parsed the flags in such a way that I can list the flags in any order, including the radius option which is followed by a number, and sort them all afterward.&lt;br /&gt;&lt;br /&gt;This will, of course, come in handy for other things, particularly my interim rig building tools until I start doing some interface building. &lt;span style="font-style: italic;"&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Drawbacks:&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;Lots of positives for this technique, but I'm annoyed by the fact that I can't just arrow up and recall the options. For now, I have it echoing the input options so I can copy and paste them at least. If this becomes an annoyance, I'll just make some sort of interface that stays available with radio buttons.&lt;span style="font-style: italic;"&gt;&lt;span style="font-style: italic;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-style: italic;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19305204-113359891476609639?l=car2ns3d.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://car2ns3d.blogspot.com/feeds/113359891476609639/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19305204&amp;postID=113359891476609639' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19305204/posts/default/113359891476609639'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19305204/posts/default/113359891476609639'/><link rel='alternate' type='text/html' href='http://car2ns3d.blogspot.com/2005/12/scripts-with-flags.html' title='Scripts with flags'/><author><name>Stephen Greenberg</name><uri>http://www.blogger.com/profile/16640921787080104112</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19305204.post-113324991006963034</id><published>2005-11-28T23:15:00.000-08:00</published><updated>2005-11-29T02:14:05.936-08:00</updated><title type='text'>Switching by object picking</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Rigging&lt;/span&gt;&lt;br /&gt;Solved the eye stretching problem with additional spurs.&lt;br /&gt;Went through rig and renamed a lot of joints and controls.&lt;br /&gt;Got ear controls working. Ear cluster selections can be hidden from the head control Enum switch, as well as activating and deactivating them. Used combination of IK twist and roll, and an added locator to move surrounding bones, in addition to cluster rotation.&lt;br /&gt;Model fixes around eyes.&lt;br /&gt;First pass skinning is done.&lt;br /&gt;Got jaw working.&lt;br /&gt;Added pupil size controls.&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Planned improvements:&lt;/span&gt;&lt;br /&gt;Jaw and whisker controls.&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&lt;span style="font-style: italic;"&gt;&lt;span style="font-style: italic;"&gt;&lt;span style="font-style: italic;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;Head topology controls.&lt;br /&gt;Controls for retractable claws.&lt;br /&gt;   Updated 2am 11/29: Added wire spheres for visible cluster hierarchy axes.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Scripts&lt;/span&gt;&lt;br /&gt;Well, I &lt;span style="font-style: italic;"&gt;had&lt;/span&gt; written a script today. earSelect.mel. But it's already obsolete.&lt;br /&gt;&lt;br /&gt;I finally figured out how to make a self contained character which doesn't need external scripts for such things as selecting an object and that selects another object and deselects itself. I used this for ear cluster selection controls. The same process also helped me figure out how to make the foot axis switch work without having an extra "spare" channel in the expression. Essentially, I found that I could write an expression as a "global proc" and then run a script job that calls it, all within the .mb file. I also figured out how to turn the selection feature on and off. The current selection expression is completely brute force. I'm hoping I can figure out a more efficient way to state the expression.&lt;br /&gt;&lt;br /&gt;This was one of those revelations that I couldn't find a single example of, other than using the Maya help file examples. I just put a couple of things together.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Planned improvements:&lt;/span&gt;&lt;br /&gt;I still need to figure out how to make the object switch so I can use "undo". Right now, it hits "undo" and that actually calls the script again and contravenes the process of "undoing".&lt;br /&gt;&lt;br /&gt;   Updated 2am 11/29: Done. Undo works properly now.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19305204-113324991006963034?l=car2ns3d.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://car2ns3d.blogspot.com/feeds/113324991006963034/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19305204&amp;postID=113324991006963034' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19305204/posts/default/113324991006963034'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19305204/posts/default/113324991006963034'/><link rel='alternate' type='text/html' href='http://car2ns3d.blogspot.com/2005/11/switching-by-object-picking.html' title='Switching by object picking'/><author><name>Stephen Greenberg</name><uri>http://www.blogger.com/profile/16640921787080104112</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19305204.post-113307030653202989</id><published>2005-11-26T21:31:00.000-08:00</published><updated>2005-11-27T12:36:53.510-08:00</updated><title type='text'>Stretchy Head</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Rigging&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I've finally figured out how to get my idea for a stretchy head which also allows some topological control, working. It's not perfected yet, but I'm getting closer. I can get pretty close to proper skin assignments on the initial smooth skin pass, so won't need tons of vertex reassignment.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Scripts&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;sphereAB //This makes two spheres used by makeStretchyChain, and locates the first at a selected bone, the second offset by a command line input. Can probably be used for other auto creation functions.&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Plans for improvements:&lt;span style="font-style: italic;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;/span&gt;Ability to set number of spheres.&lt;br /&gt;addCrazyLoc //Makes a locator with the .name attribute so I can test out scripts that use it for naming new objects.&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Plans for improvements:&lt;/span&gt;&lt;br /&gt;    Right now, this is character specific. I will make it so it can add a locator with the .name&lt;br /&gt;    attribute  for other characters, or multiple characters. At that point, I'd have to update&lt;br /&gt;    the other tools to accommodate multiple characters.&lt;br /&gt;spurBuilder //Creates 6 bone spurs for directing smooth skin assignments, and parents them to the selected bone or object. Command line radius from a selected parent bone or other object. This one has been a huge time saver. Auto-names with SPUR prefix and selected object's name.&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Plans for improvements&lt;/span&gt;&lt;br /&gt;    Adjustable number of bones&lt;br /&gt;      Accommodation for compound names that have _L and _R in them.&lt;br /&gt;    Ability to automatically decide which character is being used in multiple character situations.&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19305204-113307030653202989?l=car2ns3d.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://car2ns3d.blogspot.com/feeds/113307030653202989/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19305204&amp;postID=113307030653202989' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19305204/posts/default/113307030653202989'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19305204/posts/default/113307030653202989'/><link rel='alternate' type='text/html' href='http://car2ns3d.blogspot.com/2005/11/stretchy-head.html' title='Stretchy Head'/><author><name>Stephen Greenberg</name><uri>http://www.blogger.com/profile/16640921787080104112</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19305204.post-113294851088323892</id><published>2005-11-25T09:31:00.000-08:00</published><updated>2005-11-25T11:55:10.923-08:00</updated><title type='text'>Catching up, part 2</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Scripting&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;As part of my dual front self-training methodology, I'm writing scripts while working on my rig. This gives me a way to focus my energies, rather than working on generalized scripting tutorials.&lt;br /&gt;&lt;br /&gt;When I find that I'm doing something repetitively, I write a script. Since I'm taking use of a character in a pipeline into consideration, a big part of my goal is control of object and node names.&lt;br /&gt;This is a major reason I'm working on my own rigging script. If I get a character TD job, I'd like to bring in my tools and know what part of the script to alter to accommodate an existing pipeline.&lt;br /&gt;&lt;br /&gt;I'm also finding that as I learn how to write tools of my own, it gives me an idea of what to look for in existing scripts: commands, methodologies, naming conventions and processes. I'm trying to make my scripts clearer for others to follow, and that means eschewing the convenience of short string names for more descriptive ones that can be followed from one process to another.&lt;br /&gt;&lt;br /&gt;The scripts I've created so far, of course, duplicate the utility of more elegant ones that can be found on places like High End 3D. I'm avoiding even looking at what's in those scripts so I can learn to build my own instead of just copying what already exists. Most are difficult to follow anyway, because they have nice, user friendly interfaces and the origin of variables is somewhat obscured.&lt;br /&gt;&lt;br /&gt;Here's what I've got so far:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Start script job&lt;/span&gt; //activates a script job for a continually used command by character controls&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;autoJoint&lt;/span&gt; //this is the first version of my foot pivot switch. I've since deployed a version of this as an expression.&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;clippingPlane&lt;/span&gt; //sets the clipping planes on all cameras from the defaults when the units are changed so you can actually see objects.&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;makeFootPivot&lt;/span&gt; //creates all of the objects which represent the various foot axes, aligns them to the joints and creates the attributes on the foot controller to switch them.&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Plans for improvements:&lt;/span&gt;&lt;br /&gt;    Generalize to accommodate different character names&lt;br /&gt;    Use loops instead of discreet commands&lt;br /&gt;    Automatically create expressions&lt;br /&gt;    Create foot object space switching.&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;pivot switching expression&lt;/span&gt; //adapted the autoJoint script to an expression to avoid need for script job&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;alignObjects &lt;/span&gt;&lt;span style="font-style: italic;"&gt;//&lt;/span&gt;my version of the "align objects" tool in Max. I wrote this to be able to discreetly control alignment of object in space and orientation and can call this within other scripts when building and orienting objects.&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;clusterer &lt;/span&gt;//creates clusters on CVs in the order they were picked. Still needs work because of the way Maya represents multi-selection of CVs. Works now only if I pick CVs in reverse order.&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;syncLoc &lt;/span&gt;//creates a locator for each object selected, aligns it, then constrains the original objects to the locator synchronized to it.&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Plans for improments:&lt;/span&gt;&lt;br /&gt;    Flag system to choose point, orient, point and orient, or parent&lt;br /&gt;    Command line entry to choose an object class. Currently each new locator is given the class "LOC"&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;renamer &lt;/span&gt;//this allows a selected group of objects to be renamed, with each new object having a number suffix (_1, _2, _3) added to the end.&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;renamerA &lt;/span&gt;//same as renamer, but letters are added to the end instead to avoid confusion with Maya's auto numbering scheme for duplicate objects (_A, _B, _C). At present, it only allows for renaming of 26 objects before it runs out of letters, but I haven't come close to renaming more than that yet.&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Plans for improvements:&lt;span style="font-style: italic;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;/span&gt;Combine renamer and renamerA with flag system&lt;br /&gt;    Add "prefix only" mode&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;geoConstraint &lt;/span&gt;//this is a tool that will constrain a group of selected objects to the surface of another object.&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;multiConstraint&lt;/span&gt; //this works like geoConstraint, only it constrains the multiple selected objects with a point, orient, or point and orient constraint. I'll probably combine the two with expansion of my flag system later.&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;syncLocParent &lt;/span&gt;//like syncLoc, only does a parent. This will be folded into syncLoc when I get to it.&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;stretchySkel&lt;/span&gt; //actually less functional than it sounds. This was the first script I created to speed up creation of a stretchy skeleton. All it does it connect the mult/divide node to the .tx of selected joints.&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;syncLocNoneg&lt;/span&gt; //this creates synchronized locators but doesn't constrain or parent anything to them. It has the additional function of parsing the object name and automatically giving the new locator the same name, but with object class changed.&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;makeStretchyChain&lt;/span&gt; //my current version of this creates a joint chain between two objects, aligns the axes of the joints, adds an IKSpline solver, adds the nodes nodes and connects attributes that make the chain stretchy. I have two versions of this: one uses joint translation and one uses joint scaling to make the chain stretchy. Command line options allow setting the number of joints, and the appendage name. Joints are sequentially suffixed with letters (_A, _B, etc.).&lt;br /&gt;&lt;br /&gt;This last one took some time to evolve and trouble shoot. While I'd figured out how to make a stretchy chain manually several months ago, automating the process took some figuring out.&lt;br /&gt;&lt;br /&gt;The development of the script proceeded in logical parts. This all started sometime Tuesday (11/22) when I was making all sorts of stretchy chains to test out various ideas on the head distorting thing. This is essentially something you'd only do on a cartoon character, but that's what I wanted to do right now. I haven't gone back to the head tweaking problem solving yet, and the chain idea is probably overly complicated for the results I want to achieve. But if it takes 10 stretchy chains to achieve the results reliably without compromising other controls, so be it. I needed a fast way to draft chains, and I'd have to make a script like this eventually if I want to have my very own rig building script, right? And I'm not about to let a little fact like the one that I just started learning scripting less than two weeks before, and that this might be overly ambitious at the moment, stop me, am I?&lt;br /&gt;&lt;br /&gt;I'll start from the beginning.&lt;br /&gt;&lt;br /&gt;It took a while to figure out how to build the joints where I wanted them.&lt;br /&gt;&lt;br /&gt;First I thought I'd just build them evenly between two objects. This meant calculating world x y z euclidean coordinates between two points. I cobbled the xform part of the joint switching script to get the world space coordinates of the spheres, and just did simple math. The approach worked OK, but wasn't all that flexible. Sometimes the joints don't follow a straight line path.&lt;br /&gt;&lt;br /&gt;I decide to build the joints along a curve. So first I had to build the curve. That became the first part of the script, still using the xform lines from the first version. The second part would have been easy if I knew what I was doing. In this case, the search for the right node took longer than usual, probably because I was trying to figure this out at 3am. I wasn't going to go to sleep until I figured this out.&lt;br /&gt;&lt;br /&gt;The magic bullet was the pointOnCurveInfo node. I did some manual experimenting with it to find out how to get the info I wanted. Finally, I figured out how to use a percentage to get the position info out. I just added a loop that divided 1 by the number of joints, got the percentage and successively added each joint to the new position. Anyone reading this can tell I'm proud of the fact that I figured this out. To me, it was a profound revelation, because I can think of all sorts of uses for this tool.&lt;br /&gt;&lt;br /&gt;Now...I'm sure I could have just found out the answer to this by dumpster diving existing code (this is not to say existing code is trash, it's just hard to find what you're looking for when you don't know exactly what you're looking for). But when you wrack your brain to figure something out yourself, you tend to learn more thoroughly, and along the way think of other places the information can be useful. Sometimes you find stuff that's totally irrelevant to the task at hand, that comes in handy later on.&lt;br /&gt;&lt;br /&gt;The rest of the first draft of the stretchy joint code was pretty straightforeward. I just manually built the stretchy part in the interface, looked at the script editor, and translated that into loops and conditional statements. Couple of glitches plagued me: I was using specific object names for curves and nodes the script was creating. Problem was, on repeated testing of the script and diagnosing failures to get the desired results, new nodes and curves were created, and subsequent ones created by the script were getting suffix ascended.  So the script would try to use the old ones, which were wrongly assembled. It finally occurred to me that this was happening, and I made an objExists check. My first use of that command, though I knew it existed.&lt;br /&gt;&lt;br /&gt;Finally, I get it all working. Except that it doesn't work as well as my hand assembled versions. Examining the entrails, I found that the joints were oriented wrong. And when I used Jason Schleifer's jsOrientJointUI2 script to fix them, they worked fine.&lt;br /&gt;&lt;br /&gt;I tried to deconstruct jsOJUI2 to see how it worked and to add that scripting to my script. My effort at cheating was resoundingly thwarted by the complexity of the script. I also knew, deep down, that if it worked in the interface but not my script, even though it almost worked in my script, I was missing something fundamental. So I posted on Schleifer's forum just before midnight Wednesday (11/23). I stayed up another three hours trying to figure it out, but I was just Wile E. Coyote-ing: losing sight of the goal through obsession.&lt;br /&gt;&lt;br /&gt;Yesterday morning, before Thanksgiving Linner and the family gathering, I sat down and systematically broke the problem down. I copied and pasted portions of the script in the script editor and executed them. I checked the orientation by turning on the display of the rotation axes. I compared them to the joints built manually. I looked at the script editor as I made the joints. Well what do you know? After the first joint, subsequent joints have a command that aligns the joints. DUH! All I needed to add to make the joints align properly was a conditional statment in the joint construction loop: if ($counter    &gt;0)&lt;br /&gt;            {joint -e -zso -oj xyz -sao yup $jointname[($counter - 1)];}&lt;br /&gt;&lt;br /&gt;What's the point of explaining all this? Well...documenting the learning process isn't just about what I did and when for me. What I  learn by the process of goal, failure, tenacity and finally success took me down all sorts of roads that I saw all sorts of sights on. I know a lot more ways of doing something wrong now, and I saw solutions to problems that I've only vaguely started thinking about. But I expect that if I work as a character TD somewhere, I'm going to have to improvise and solve puzzles all the time.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19305204-113294851088323892?l=car2ns3d.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://car2ns3d.blogspot.com/feeds/113294851088323892/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19305204&amp;postID=113294851088323892' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19305204/posts/default/113294851088323892'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19305204/posts/default/113294851088323892'/><link rel='alternate' type='text/html' href='http://car2ns3d.blogspot.com/2005/11/catching-up-part-2.html' title='Catching up, part 2'/><author><name>Stephen Greenberg</name><uri>http://www.blogger.com/profile/16640921787080104112</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19305204.post-113293958971751346</id><published>2005-11-25T08:18:00.000-08:00</published><updated>2005-11-25T11:58:31.830-08:00</updated><title type='text'>Catching up, Part 1</title><content type='html'>This is where I'm at now.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Rigging&lt;/span&gt;&lt;br /&gt;I've created my "switching pivot" control. A problem I've always thought needed addressing was that when a character walks, the foot pivots on either the heel or the ball of the foot. Most setups default to rotating around the heel so when the foot makes contact with the to in the air, it's simple to just rotate it down flat. But you don't change direction that way for the most part. When we change direction, we usually lift our heel a little and pivot on the ball of the foot.&lt;br /&gt;&lt;br /&gt;The solutions I've seen seem inadquate. On my last Maya character, which I called "&lt;a href="http://casadiablos.com/stephanim/dogfight_sm.mov"&gt;Alex&lt;/a&gt;", I had what now seems like the standard "swivel ball of the foot" control. The problem was, that if the character turned 180 degrees, I had to resynchronize the foot control with the ball of the foot. It was even worse at 90 degrees. This character was running all over the room. The foot pivot problem was most annoying when the foot lifted up. Synchronizing it added keys where I didn't want them, and made refining the animation much more time consuming.&lt;br /&gt;&lt;br /&gt;Another thing about the foot pivot problem, is that when our foot is up in the air, it rotates around the ankle. Having it rotate around the heel looks unnatural, and compensating for it is, once again, time consuming.&lt;br /&gt;&lt;br /&gt;This is a repeating theme in my rigging choices. Compensating for rotational pivots in the wrong place for the animation at hand and compensating for rotational hierarchies which make the extremities swing in an undesired arc not only are time consuming, but they extend the already labor and artistic intensive tasks in refining the animation.&lt;br /&gt;&lt;br /&gt;So I created a pivot switching feature for the foot. This has evolved some in the last two weeks. I started by writing an automated system which executed a MEL script that was run as a script job. You would pick icons which represented the heel, ball and ankle. That would automatically switch the pivots. After testing this out on the character, I found that this was unsuitable because you had too many controls too close together. My current version has a pull down menu in the channel box which allows you to choose the rotational preference. This is animatable. When the pivot is switched, I have iconic representation on the foot with objects that represent the heel, ball and ankle pivots which can be seen at a glance. The icons are non-selectable. At present, I haven't figured out a way to color them for highlighting at the same time they are a "reference" object. I also haven't figured out a way to make the system work without keying the rotate pivot and rotate translation pivot channels, and having them visible. On top of that, the expression only executes if I have an active connection specified in the visible channel box. Even if I can't solve those problems, it's not too big an inconvenience. Just means that adjusting keys during the animation involves moving a lot more channels for the feet. But it all works, and that's what's important right now.&lt;br /&gt;&lt;br /&gt;The foot also has a hierarchy switching mode. At present, it switches between "World", where the body moves and the feet stay stationary until you move them, and a "Body" mode, where the foot moves with the main COG control. So if a character does a flip, an animator doesn't have to manually keyframe the arc, they just have to worry about the placement of the feet relative to the body. As would occur naturally.&lt;br /&gt;&lt;br /&gt;Another thing that I've wanted to add for a long time is a switch for the hand space. I now have a pull down menu in the channel box with 7 IK hand modes. I also have a pull down menu on the clavicle which isolates the rotation of the shoulder from the rest of the body. The hands can each be selected to rotate with the body, remain attached to the world, translate with the body and clavicle without inheriting rotation, ignore the clavicle but still move with the body, and nearly every combination of all these. In addition, the hand can be used in a semi-FK fashion by rotating the clavicle control. The clavicle control has been modified as a target, rather than rotation control for the clavicle itself. Move it up, the clavicle rotates up. Move it forward, the clavicle rotates forward. This method allows the clavicle control to be used both for rotating the arm from the shoulder FK style, and rotating the clavicle simulataneously. The switches are animatable and easily accessed from the channel box. There are 14 possible combinations between the hand and clavicle controls, but I'd imagine an animator would stick to 2 or 3 depending on their preference.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Plans for further improvements:&lt;br /&gt;&lt;/span&gt;Stretchy switch to turn off the stretchy IK&lt;br /&gt;Spline IK for the ability to give the arm a more "rubber hose" kind of shape, with adjustable hardness on the elbow. As I currently envision it, this control will also allow for the appearance of "successive breaking of the joints" in IK mode.&lt;br /&gt;I think the FR rig allows for stretchy fingers. But I plan on devising my own system.&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&lt;/span&gt;&lt;br /&gt;I've also created a pull down control for the head, to isolate the head rotation from that of the body. This makes it a lot easier to achieve overlapping action in the head without counter-rotation. The default is FK, but the switch is simple and animatable.&lt;br /&gt;&lt;br /&gt;I'm currently working on some sort of system for distorting the head. So far, I have found that using a wrap deformer has too many pathologies, the main one being that it is additive to the joints. The character has long ears in this case, and the wrap deformer has worked against every method I've come up with for discreet control of the ears. I've also had problems so far in deploying wire deformers. I plan to continue trying to find a viable solution to this today, experimenting with the many deformation tools available in Maya.&lt;br /&gt;&lt;br /&gt;Last, I successfully came up with a way to control the eyes no matter how much they're distorted. The pupil stays the same size and shape regardless of what happens with the topology of the eyeballs themselves. This was more challenging than I thought, but the solution I chose is working perfectly. I also figured out a way to make the eyelids conform to the eyeball when they're opened and closed, regardless of changes in the eyeball's topology.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Plans for further improvements:&lt;/span&gt;&lt;br /&gt;I'd like to add controls to adjust the shape of the eyelids, since this character doesn't have eyebrows, to accommodate emotional states.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19305204-113293958971751346?l=car2ns3d.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://car2ns3d.blogspot.com/feeds/113293958971751346/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19305204&amp;postID=113293958971751346' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19305204/posts/default/113293958971751346'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19305204/posts/default/113293958971751346'/><link rel='alternate' type='text/html' href='http://car2ns3d.blogspot.com/2005/11/catching-up-part-1.html' title='Catching up, Part 1'/><author><name>Stephen Greenberg</name><uri>http://www.blogger.com/profile/16640921787080104112</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19305204.post-113293544038923295</id><published>2005-11-25T07:56:00.000-08:00</published><updated>2005-11-25T09:31:06.660-08:00</updated><title type='text'>The blog begins</title><content type='html'>I decided to start this blog to document, among other things, my learning progress in Maya rigging. I think there's a kind of distrust of people who are self taught at anything, particularly when they have no education background in what they're teaching themselves. Probably for good reason, since it isn't easy. And too many people lie.&lt;br /&gt;&lt;br /&gt;I'm learning Maya rigging and MEL scripting because, well, just being an animator isn't good enough anymore. At least not if I want to gain employment in Los Angeles, where I live and where the people who seem to be the best at everything tend to congregate. While I know something about rigging from years of experience with Softimage and Alias Poweranimator, there are a lot of new tools available these days, and MEL commands offer a whole new level of controls I can add to characters, using tools I'd never have guessed existed. I'm pretty excited about this.&lt;br /&gt;&lt;br /&gt;I've put off learning MEL scripting because it's completely antithetical to artistic thinking. But now that I'm getting into it, it satisfies some part of my brain that enjoys solving puzzles. So does rigging a character. You figure out what result you're looking for, and work backwards. Breaking the problem into a series of smaller problems and solving them one by one.&lt;br /&gt;&lt;br /&gt;The learning resources I'm using at this time are &lt;a href="http://www.alias.com/glb/eng/products-services/learning_tool_details.jsp?itemId=1200011"&gt;The Jason Schleifer Rigging Bundle&lt;/a&gt; and &lt;a href="http://www.melscripting.com/"&gt;Mel Scripting for Maya Animators&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I'm not following these references sequentially. Instead I decided to start by actually rigging a character. The character, KrazyCat (kind of a "Bill The Cat"-esque character), is one I actually bought since I feel that modeling a character from scratch at this time is just a distraction from my ultimate learning goals. I've changed the model somewhat to make it more amenable to animation.&lt;br /&gt;&lt;br /&gt;In this first pass, rather than starting by building a rig from scratch, I decided to start with a rigging tool called &lt;a href="http://www.tutorialized.com/tutorial/Using-Final-Rig-1.0/4818"&gt;Final Rig&lt;/a&gt;. I rightly figured I could see what features existed in a modern rig, and modify it piece by piece with my own ideas. Eventually, when I've settled on the features I want in a rig, I'll build a new one from the ground up with my own built from scratch rigging script (for which I've already started writing the base scripts).&lt;br /&gt;&lt;br /&gt;I started all this about two weeks ago, and wish I'd started earlier.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19305204-113293544038923295?l=car2ns3d.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://car2ns3d.blogspot.com/feeds/113293544038923295/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19305204&amp;postID=113293544038923295' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19305204/posts/default/113293544038923295'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19305204/posts/default/113293544038923295'/><link rel='alternate' type='text/html' href='http://car2ns3d.blogspot.com/2005/11/blog-begins.html' title='The blog begins'/><author><name>Stephen Greenberg</name><uri>http://www.blogger.com/profile/16640921787080104112</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
