Rigmarole Bloghttps://chrislesage.com/2016-11-28T16:30:00-05:00Sliding and Bulging Effects Using Soft Mods in Maya2016-11-28T16:30:00-05:002016-11-28T16:30:00-05:00Chris Lesagetag:chrislesage.com,2016-11-28:/posts/sliding-bulging-effects-with-softmods/<p>In this Maya rigging tutorial, you will learn <strong>how to animate the falloff center of a Soft Mod.</strong> This lets you animate a bulge moving along an object.</p>
<p><img alt="sliding softmod" src="https://chrislesage.com/images/sliding_softmod.gif"></p>
<p>I worked as the character rigger on a fantastic short film called <a href="https://www.youtube.com/watch?v=vbMQfaG6lo8" title="Majora's Mask - Terrible Fate">“Majora’s Mask - Terrible Fate”</a> by <a href="http://www.emberlab.com/" title="Ember Lab website">Ember Lab</a>. I used Soft Mods in Maya to create a bulging effect in the Mask Salesman’s backpack. This makes it look like objects are bouncing around inside the fabric. By connecting it …</p><p>In this Maya rigging tutorial, you will learn <strong>how to animate the falloff center of a Soft Mod.</strong> This lets you animate a bulge moving along an object.</p>
<p><img alt="sliding softmod" src="https://chrislesage.com/images/sliding_softmod.gif"></p>
<p>I worked as the character rigger on a fantastic short film called <a href="https://www.youtube.com/watch?v=vbMQfaG6lo8" title="Majora's Mask - Terrible Fate">“Majora’s Mask - Terrible Fate”</a> by <a href="http://www.emberlab.com/" title="Ember Lab website">Ember Lab</a>. I used Soft Mods in Maya to create a bulging effect in the Mask Salesman’s backpack. This makes it look like objects are bouncing around inside the fabric. By connecting it to controllers, it makes it very animator-friendly.</p>
<p><img alt="sliding softmod backpack" src="https://chrislesage.com/images/sliding_softmod_backpack.gif"></p>
<h3>Why Soft Mods?</h3>
<p>Soft Mods and Lattices have some very interesting properties. They are non-linear deformers that you can easily shape and manipulate. You can also <em>move geometry through</em> their deformer space.</p>
<p>This lets you create some nice <strong>bulging, sliding and bending effects</strong> that you can move along your geometry using controllers. In a future tutorial, I’ll show you how you can use lattices in similar clever ways.</p>
<p>The Mask Salesman’s backpack rig uses 4 Soft Mods. Each controller has attributes to animate the size and strength of the bulge. By making it small, it looks like an object bouncing around inside the bag. By making it large, it can look like the entire bag has some nice dynamic bounce, without needing a real simulation.</p>
<h3>Other Examples</h3>
<p>Here are some other examples of ways I’ve used this in rigs. I’ll show some of this in future tutorials.</p>
<ol>
<li>Create a bend in a creaky old piece of wooden flooring, wherever the character steps down on the floor. The animator can choose where the bend will happen for each footstep.</li>
<li>A character grabs and slides open a window curtain. The animator was able to create a fairly convincing shape, and that animation was sent to the cloth simulation department for some extra finesse.</li>
<li>Hiding the end of a rope inside a machine as it coils up using a lattice.</li>
<li>Create a cartoony water-hose effect through a hose or a character.</li>
</ol>
<h2>How to set this up</h2>
<p><img alt="softmod rigging cheat sheet" src="https://chrislesage.com/images/softmod_cheat_sheet.png"></p>
<ol>
<li>
<p>Select the geometry you want to deform, or select some vertices on the geometry.</p>
</li>
<li>
<p>Create a softMod deformer with the default options. Click <strong>Deform -> Soft Modification</strong>. You’ll edit the radius and other parameters with controls later.</p>
</li>
<li>
<p>Create 2 controllers. <strong>ControlA</strong> is going to slide where the Soft Mod center begins. <strong>ControlB</strong> will move the Soft Mod handle. Parent <strong>ControlB</strong> under <strong>ControlA</strong>. Also create a <strong>locator</strong>. Keep the locator in world space for now.</p>
</li>
<li>
<p>Parent constrain the <strong>locator</strong> to follow <strong>ControlA</strong> with “Maintain Offset” turned off.</p>
</li>
<li>
<p><strong>Connect locator.translate</strong> to the <strong>softMod1.falloffCenter</strong>. Your goal here is to get the world position of <strong>ControlA</strong>. Since the <strong>locator</strong> follows the control, it is essentially giving you the world position. Depending on your skill level, you can also use utility nodes to get the world position of <strong>ControlA</strong>.</p>
</li>
<li>
<p>Connect <strong>ControlB.translate</strong> to <strong>softMod1Handle.translate</strong> and <strong>ControlB.rotate</strong> to <strong>softMod1Handle.rotate</strong>. You will want to use a <strong>connection</strong> instead of a constraint, or you will get double-transformations on the Soft Mod.</p>
</li>
<li>
<p><strong>Add attributes</strong> on <strong>ControlB</strong> so the animator can animate the envelope and the radius of the Soft Mod without having to select the Soft Mod. I suggest you use animator-friendly names like “strength” and “size”. Connect strength to envelope. And size to radius. You can then hide the Soft Mod Handle.</p>
</li>
</ol>
<p><br></p>
<p>Here is a <strong><a href="http://chrislesage.com/downloads/soft_mod_slider.zip">Maya scene file to download</a></strong> and study.</p>
<p><br></p>
<h2>Some advanced tips to take this further</h2>
<h4>Attach it to a surface</h4>
<p>In the backpack example, I used a geometry constraint to attach the Soft Mod to the contours of the backpack. This lets the animators slide it <em>along</em> the backpack. The control can move anywhere, but the world-space locator from step #5 is constrained to the surface of a nurbs sphere that is roughly modelled to the shape of the backpack.</p>
<p><img alt="softmods sliding on surface" src="https://chrislesage.com/images/softmods_on_surface.png"></p>
<h4>Control where the Soft Mod gets created</h4>
<p>If you want to control where the <strong>default position</strong> of the Soft Mod will be, start by selecting a few vertices at that position. The Soft Mod handle will be created at the center of your vertex selection. Then, you can add the rest of the vertices later using the “Edit Membership Tool”.</p>
<h4>Cartoony rubber hose effects</h4>
<p>If you want to make a cartoony rubber-hose effect, use a path constraint to attach the locator to a curve that follows the hose. Or use deformation order to move the Soft Mod along a straight hose <em>before</em> bending it with your other controllers. Here is a rough rig prototype for a cartoony character.</p>
<p><img alt="cartoony belch rig prototype" src="https://chrislesage.com/images/cartoon_belch_prototype.gif"></p>
<h4>Control the falloff effects</h4>
<p>Experiment with the falloff settings of the Soft Mods to get more linear effects. For example, by turning off Falloff X, you can get a different effect than just a simple round bump.</p>
<p><img alt="sliding softmod falloff X" src="https://chrislesage.com/images/sliding_softmod_x_falloff.gif"></p>
<p>The setting for falloff is found on the Soft Mod deformer. If you need a very specific shape, sometimes a lattice works better.</p>
<p><img alt="softmod falloff X example" src="https://chrislesage.com/images/softmod_falloff.png"></p>
<h3>Thanks for reading!</h3>
<p>Thanks for reading! If you have any questions or comments about these steps, feel free to send me a message on my contact form. Want to learn more rigging techniques and tips like this? Make sure to sign up below.</p>
<p><br></p>
<style type="text/css">
#mc_inline_signup input.email {
display: block;
padding: 6px 0;
font-size: 15px;
margin: 0 4% 10px 0;
text-indent: 5px;
width: 58%;
min-width: 220px;
margin-left: 6px;
line-height: 14px;
border-radius: 3px;
}
#mc_inline_signup input.fname {
display: block;
padding: 6px 0;
font-size: 15px;
margin: 10px 4% 10px 0;
text-indent: 5px;
width: 58%;
min-width: 220px;
margin-left: 6px;
line-height: 14px;
border-radius: 3px;
}
#mc_inline_signup {
background: #fff;
clear: left;
border: 1px solid black;
font: 14px;
width: 450px;
max-width: 450px;
border-radius: 3px;
}
#mc_inline_signup input.button {
display: block;
margin: 0 0 11px 0;
width: 220px;
min-width: <span class="caps">220PX</span>;
margin-left: 6px;
}
#mc_inline_signup .button {
clear: both;
background-color: #e07006;
border: 0 none;
border-radius: 4px;
color: white;
font-size: 15px;
font-weight: bold;
height: 34px;
line-height: 31px;
padding: 0;
text-align: center;
text-decoration: none;
vertical-align: top;
white-space: nowrap;
}
#mc_inline_signup input {
border: 1px solid grey;
-webkit-appearance: none;
}
#mc_inline_signup form {
display: block;
position: relative;
text-align: left;
padding: 20px 0 8px 3%;
}
#mc_inline_signup label {
display: block;
font-size: 16px;
padding-bottom: 0px;
font-weight: bold;
color: #000;
margin-right: 10px;
}
</style>
<div id="mc_inline_signup" style='border-radius: 5px;'>
<form action="http://chrislesage.us6.list-manage1.com/subscribe/post?u=b8abd9a567ffbdb2e4195146a&id=ddea5a33af" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_blank" novalidate>
<label for="mce-EMAIL" style="margin-left:6px;">Sign up for the Rigmarole Tech Art Newsletter</label>
<input type="text" value="" name="FNAME" class="fname" id="mce-FNAME" placeholder="First Name">
<input type="email" value="" name="EMAIL" class="email" id="mce-EMAIL" placeholder="Enter your E-mail" required>
<div class="clear"><input type="submit" value="Subscribe" name="subscribe" id="mc-embedded-subscribe" class="button"></div>
</form>
</div>Using Edge Slide and Falloff to Fix Lip Topology in Modo2015-05-19T16:00:00-04:002015-05-19T16:00:00-04:00Chris Lesagetag:chrislesage.com,2015-05-19:/character-rigging/powerful-retopology-tools-in-modo/<p>Here is a new character I’ve been working on. I’m modelling him to be rigged and animated along with a face rig. The base sculpt and colors were done in 3D-Coat. I used voxel painting to lay in some rough colors without needing UVs.</p>
<p><img alt="chris_lesage_alien_turtle" src="http://chrislesage.com/wp-content/uploads/2015/05/chris_lesage_alien_turtle.gif"></p>
<p>Now I’m taking it into Modo to do some more technical topology clean up, and I’ll finish the UVs and texture maps in Modo. I’m quite new to Modo, but I …</p><p>Here is a new character I’ve been working on. I’m modelling him to be rigged and animated along with a face rig. The base sculpt and colors were done in 3D-Coat. I used voxel painting to lay in some rough colors without needing UVs.</p>
<p><img alt="chris_lesage_alien_turtle" src="http://chrislesage.com/wp-content/uploads/2015/05/chris_lesage_alien_turtle.gif"></p>
<p>Now I’m taking it into Modo to do some more technical topology clean up, and I’ll finish the UVs and texture maps in Modo. I’m quite new to Modo, but I’m already picking up some amazing new tricks, and I’ll show you a bit in this post.</p>
<p>Some of my original rough sketches done in the online sketch tool, <a href="http://www.zefrank.com/scribbler/scribblertoo/">Scribbler</a></p>
<p><img alt="chris_lesage_alien_turtle_sketch1" src="http://chrislesage.com/wp-content/uploads/2015/05/chris_lesage_alien_turtle_sketch1.jpg">
<img alt="chris_lesage_alien_turtle_sketch2" src="http://chrislesage.com/wp-content/uploads/2015/05/chris_lesage_alien_turtle_sketch2.jpg"></p>
<p>While this guy sort of resembles a turtle with his shell, I’m going to make his skin translucent and colourful like a frog.</p>
<h2>Editing the Mouth Topology Using Edge Slide <span class="amp">&</span> Falloffs</h2>
<p>3D-Coat has some amazing topology tools, but I find it a bit difficult to do very precise and complex operations in very small areas like the mouth cavity, lips and eyelids. I feel a lot more confident to make these changes in Modo. You have great topology tools as well, but it is well integrated with all of the snapping, falloff and modelling operations. So you can seamlessly switch between sculpting and modelling, and do things like Bridge or Bevel or Thicken.</p>
<p>You can even copy/paste polygons to make new geometry like eyebrows or clothes or break apart existing geometry to make big fast structural changes. (With all the powerful features of Modo, the simple ability to cut, copy and paste geometry as easily as text is one of my favourite parts of the whole program.)</p>
<p>First I need to make a topology fix in the corner of his mouth.</p>
<p>I went from this topology with square poly-turns right in the corner of his mouth:</p>
<p><img alt="square_mouth_topology" src="http://chrislesage.com/wp-content/uploads/2015/05/square_mouth_topology.jpg"></p>
<p>To this, with a radiating pattern around the entire lips. The first version might have worked, but having the radiating rings is more flexible for making cartoony lip shapes like puckering and a small mouth <span class="caps">OOH</span>. Making this change was relatively easy with the Topology Pen.</p>
<p><img alt="ring_mouth_topology" src="http://chrislesage.com/wp-content/uploads/2015/05/ring_mouth_topology.jpg"></p>
<p><span class="caps">BUT</span>, now there is a slow turning of the lips. The outer edge of the upper lip slowly rolls inwards, so that by the time it gets to the bottom, it is inside the mouth. I’ll fix this.</p>
<p><img alt="bad_spinning_mouth_topology" src="http://chrislesage.com/wp-content/uploads/2015/05/bad_spinning_mouth_topology.jpg"></p>
<p>I’ll use <strong>Edge -> Slide</strong> to handle this. The amazing thing about Modo is that all of these poly modelling tools integrate with snapping and falloff. So you can use Linear Falloff so the Slide happens more near the center, and less towards the corner of the mouth.</p>
<p><img alt="modo_linear_falloff_ease_in" src="http://chrislesage.com/wp-content/uploads/2015/05/modo_linear_falloff_ease_in.jpg"></p>
<p>First I drag a <strong>Linear Falloff</strong> which you can see as a triangle with two transform gizmos in the following image. Then turn on “Ease-In” in the falloff’s properties. Then any modelling operation I do has a nice soft falloff.</p>
<p><strong>This is powerful!</strong></p>
<p><img alt="sliding_edges_with_falloff" src="http://chrislesage.com/wp-content/uploads/2015/05/sliding_edges_with_falloff.gif"></p>
<p>After sliding all the edges of the lip outwards a bit, I now have some nice clean lip topology!</p>
<p><img alt="clean_mouth_topology" src="http://chrislesage.com/wp-content/uploads/2015/05/clean_mouth_topology.jpg"></p>
<p>Thanks for reading. If you want to see more posts like this including character art, skinning, rigging and Python tutorials in Modo and Maya, make sure to sign up for updates.</p>Quickly Select and Isolate Curves in Maya’s Graph Editor2014-07-31T15:45:00-04:002016-11-16T14:28:00-05:00Chris Lesagetag:chrislesage.com,2014-07-31:/tip-of-the-day/quickly-select-and-isolate-curves-in-mayas-graph-editor/<p><strong>Here is a simple but powerful animation tip in Autodesk Maya. This is an essential tip for animators and riggers.</strong></p>
<p>In Maya, let’s say you are working in the <strong>Graph Editor</strong> with dozens or hundreds of objects, and you need to select and edit only the <em>translateY</em> curves. Here is how to select them easily.</p>
<p>First, enable the <strong>“Sync Graph Editor Display”</strong> option in the Channel Box menu.</p>
<p><img alt="sync graph editor by display setting" src="https://chrislesage.com/images/sync_graph_editor_display_setting.jpg"></p>
<p>Once that is set, you can simply select translateY in the …</p><p><strong>Here is a simple but powerful animation tip in Autodesk Maya. This is an essential tip for animators and riggers.</strong></p>
<p>In Maya, let’s say you are working in the <strong>Graph Editor</strong> with dozens or hundreds of objects, and you need to select and edit only the <em>translateY</em> curves. Here is how to select them easily.</p>
<p>First, enable the <strong>“Sync Graph Editor Display”</strong> option in the Channel Box menu.</p>
<p><img alt="sync graph editor by display setting" src="https://chrislesage.com/images/sync_graph_editor_display_setting.jpg"></p>
<p>Once that is set, you can simply select translateY in the <strong>Channel Box</strong>.</p>
<p><img alt="select_curves_by_channel_box" src="http://chrislesage.com/wp-content/uploads/2014/07/select_curves_by_channel_box1.jpg"></p>
<p>It will automatically select and isolate all the translateY curves for all selected objects in the <strong>Graph Editor</strong>.</p>
<p><img alt="select_curves_in_graph_editor" src="http://chrislesage.com/wp-content/uploads/2014/07/select_curves_by_channel_box2.jpg"></p>
<p>And of course, you can also use Shift to highlight multiple channels or Ctrl to remove channels from the highlighted list.</p>
<p>I first noticed this when I was editing 240 Driven Key curves for a mechanical prop rig. In the past I would have tediously selected all the curves in the left side channel list in the graph editor. I’m not sure when this feature was added to Maya, but I only noticed it after years of doing it the slow way.</p>
<p>Using the Channel Box is a major time saver! Tell your animators!</p>“Random Enough” - Hacking Past Your Problems When Prototyping2013-11-21T15:51:00-05:002013-11-21T15:51:00-05:00Chris Lesagetag:chrislesage.com,2013-11-21:/tech-art/random-enough-hacking-past-your-problems-when-prototyping/<p>In this blog post I’ll talk a bit about prototyping games or apps and moving quickly when stuck in a tricky programming problem.</p>
<p>I’m currently prototyping a circular puzzle game. Part of the game is about matching colors to their neighbors. I wanted a way to start the level by randomizing the blocks while having no neighboring tiles that were the same color.</p>
<p><img alt="random tiles example" src="http://chrislesage.com/wp-content/uploads/2013/11/random_tiles_example.jpg"></p>
<p>However, I didn’t want to spend the time to figure out if there was …</p><p>In this blog post I’ll talk a bit about prototyping games or apps and moving quickly when stuck in a tricky programming problem.</p>
<p>I’m currently prototyping a circular puzzle game. Part of the game is about matching colors to their neighbors. I wanted a way to start the level by randomizing the blocks while having no neighboring tiles that were the same color.</p>
<p><img alt="random tiles example" src="http://chrislesage.com/wp-content/uploads/2013/11/random_tiles_example.jpg"></p>
<p>However, I didn’t want to spend the time to figure out if there was an existing algorithm to do this. I wanted to keep coding and figuring out more important mechanics to the game, so I just made a quick while loop that would keep randomly shuffling until it found something.</p>
<p><strong>The loop took a long time to run… Sometimes several seconds or more.</strong></p>
<p>I realized that the while loop was sometimes going through hundreds or thousands of iterations. Now, I didn’t know how to visualize how complex of a problem I was trying to solve. It could have been simple or it could have been vastly complex. My goal wasn’t to visualize this problem. Instead of getting distracted on a problem whose complexity I didn’t know how to guage, I decided to cobble together a quick hack.</p>
<p>So instead, I wrote a Lua script that ran iterations of the while loop until it found some. Then, whenever it found a true result, I simply stored those combinations in a table. I ended up only finding 13 combinations. Then when I run the game, it just chooses one out of the table randomly. (Each number represents a color.)</p>
<div class="highlight"><pre><span></span>shuffleTiles = {
{4, 1, 4, 1, 3, 2, 1, 3, 2, 3, 4, 2},
{2, 1, 4, 1, 4, 2, 3, 2, 3, 1, 4, 3},
{4, 3, 4, 3, 2, 1, 3, 2, 4, 1, 2, 1},
{4, 1, 3, 2, 3, 1, 2, 4, 3, 4, 1, 2},
{3, 2, 1, 4, 1, 2, 3, 4, 2, 3, 4, 1},
{2, 4, 3, 4, 2, 1, 4, 1, 3, 2, 3, 1},
{4, 2, 3, 4, 2, 1, 3, 4, 2, 1, 3, 1},
{3, 4, 1, 3, 1, 4, 2, 3, 2, 1, 4, 2},
{3, 1, 4, 3, 2, 4, 3, 4, 1, 2, 3, 2},
{4, 1, 2, 3, 1, 2, 3, 4, 1, 2, 4, 3},
{4, 1, 2, 4, 3, 1, 2, 3, 4, 3, 2, 1},
{4, 3, 1, 2, 3, 1, 3, 2, 4, 2, 4, 1},
{1, 2, 4, 3, 1, 2, 3, 4, 1, 2, 3, 4}
}
</pre></div>
<p>Since I can also rotate the board, this results in 12 x 13 = 156 starting configurations. This is much faster than running a slow algorithm at run-time (which would last for an unpredictable amount of time) and gets me back to coding the important bits. 156 combinations is enough for me to test the game on.</p>
<p>I call this <strong><em>“random enough”</em></strong>.</p>
<p>Later on, as development continues, I can come back to solving a fast algorithm or researching if there is an existing sorting algorithm that would suit me. But if it is good enough, then I might not even need to. At this stage, my most important goal is to find a fun set of rules that results in a fun game.</p>
<p>This is one of the principles in <a href="http://www.gamasutra.com/view/feature/2438/">“How to Prototype a Game in Under 7 Days”</a>. <strong>“Nobody knows how you made it, and nobody cares.”</strong></p>
<p>The board-sorting is an important detail, but <strong><em>how</em></strong> it is sorted is a trivial one and it could potentially have cost me days of tinkering and research. It is fun to solve problems, and easy to get distracted in ways like this. When prototyping something new, my goal is to continue moving as fast as possible. You don’t want to get stuck on one little problem when you have a whole bunch more work to do.</p>
<p><strong>There are two lessons here</strong>:</p>
<ol>
<li>If you have heavy calculations to make that result in a relatively small output, it may be better to front-load the calculations and store it as data. </li>
<li>Don’t get stuck on side problems. Focus on the core problems. (Which for me is finding a fun game mechanic and designing the interactions.)</li>
</ol>
<h2>Comments (closed)</h2>
<p><strong><a href="#196" title="2014-05-23 18:22:33">Abhijit</a>:</strong> We are all guilty of falling into such traps while designing products. I agree, Random Enough is Sufficient Enough in the initial design phase.</p>A Manual Progress Bar in Scrivener2013-11-18T15:45:00-05:002013-11-18T15:45:00-05:00Chris Lesagetag:chrislesage.com,2013-11-18:/writing/a-manual-progress-bar-in-scrivener/<p>In this blog post I want to show you a cool trick for making semi-graphical Status labels in the writing program Scrivener, and then explain some of the reasons you might want to do this. I used it to make a manual progress bar. </p>
<p><img alt="scrivener_status_screenshot" src="http://chrislesage.com/wp-content/uploads/2013/11/scrivener_status_screenshot.jpg"></p>
<p>I use <a href="http://www.literatureandlatte.com/scrivener.php">Scrivener</a> and Markdown to write my blog, as well as writing documentation and training material. If you don’t know, It is a structured writing program - usually used for novels, scripts, screenplays and academic …</p><p>In this blog post I want to show you a cool trick for making semi-graphical Status labels in the writing program Scrivener, and then explain some of the reasons you might want to do this. I used it to make a manual progress bar. </p>
<p><img alt="scrivener_status_screenshot" src="http://chrislesage.com/wp-content/uploads/2013/11/scrivener_status_screenshot.jpg"></p>
<p>I use <a href="http://www.literatureandlatte.com/scrivener.php">Scrivener</a> and Markdown to write my blog, as well as writing documentation and training material. If you don’t know, It is a structured writing program - usually used for novels, scripts, screenplays and academic writing - which can output to <span class="caps">PDF</span>, <span class="caps">HTML</span>, Markdown, LaTeX, ebook, Final Draft, Word formats and more.</p>
<p><strong>So it is also a great tool for blogging, research, course notes or technical documentation for software.</strong></p>
<p>I’m currently transitioning the help docs for a Maya plugin I’m working on from Google Docs into Scrivener. The revisions/snapshots and structured nature of Scrivener make it ideal for documents which need frequent updates.</p>
<p>Scrivener already has a progress bar which is based on target word-count. That’s fine if you are aiming for a particular length in a long novel or an essay with a word target. <strong>However, you don’t always know what your target is before-hand.</strong> Especially when you are writing a lot of shorter documents such a blog posts, course notes, technical documentation or training tutorials.</p>
<p><strong>I prefer having manual control.</strong> So to simulate a percentage progress bar in Scrivener I created 6 “Status:” options using the following Unicode characters:</p>
<p><em>Note: If you are setting this up, you don’t have to enter the number codes. Just copy/paste the characters in “Project -> “Meta-Data Settings” and then click on the “Status” tab. You can paste the character there to make these statuses. The numbers are there only for reference in case they aren’t displaying properly in your browser.</em></p>
<pre>▢ - White square with rounded corners
Unicode number: U+25A2
█ - Full block
Unicode number: U+2588
░ - Light shade
Unicode number: U+2591
▒ - Medium shade
Unicode number: U+2592
▢▢▢▢▢ 0%
█▢▢▢▢ 20%
██▢▢▢ 40%
███▢▢ 60%
████▢ 80%
█████ 100%
</pre>
<p>Or if you prefer increments of 25%:</p>
<pre>▢▢▢▢ 0%
█▢▢▢ 25%
██▢▢ 50%
███▢ 75%
████ 100%
</pre>
<p>And some extras:</p>
<pre>░░░░░░░ done (published)
▒▒✘✘✘▒▒ scrapped
</pre>
<p><a href="http://chrislesage.com/wp-content/uploads/2013/11/scrivener_unicode_status.jpg">Click here to see the image if your browser isn’t displaying the unicode characters properly.</a></p>
<p>Here’s how this looks in Outline mode:</p>
<p><img alt="scrivener_unicode_screenshot" src="http://chrislesage.com/wp-content/uploads/2013/11/scrivener_unicode_screenshot.jpg"></p>
<h3>So Why Do This?</h3>
<p>Sometimes your progress depends on elements <strong>that are not related to the word-count</strong>, such as data, graphs, multimedia elements that another designer is creating, or any other amount of tasks that may need doing.</p>
<p>There is also a big difference between “finished writing”, “finished editing” and “ready to publish”.</p>
<p>Also, you may have a lot of words or notes that need a <span class="caps">LOT</span> of editing. Your rough notes shouldn’t necessarily count towards your progress. Maybe you will write 5000 words just to edit it down to 2500. Some days you will end up with less words, <strong>but you are still technically making forward progress.</strong></p>
<p>So using “Status” graphically is a way to <strong>manually</strong> set your progress, in a sort of eye-catching way.</p>
<p>You can also sort by status with this. The black bars go in the correct order, and the “done” and “scrapped” shaded bars go to the bottom, but above 0%.</p>
<p>If you want to search for other unicode characters that you can use, <a href="http://unicode-table.com/">check out this unicode website</a>. You can also copy/paste a character into this website to find out the unicode value.</p>
<p>I bet you can think of some other ideas to make some graphical reminders or just make your status labels more meaningful to you. Give it a try and let me know what you think in the comments.</p>
<hr>
<h2>Comments (closed)</h2>
<p><strong><a href="#98" title="2013-11-19 10:24:05">Chris Lesage</a>:</strong> Hey everyone. I got a few comments asking to be more specific about how to set this up. Here are some more detailed steps if you want to set this up in Scrivener. Note: All you have to do is copy and paste the unicode characters directly. <strong>You don’t have to enter the number code anywhere.</strong></p>
<ol>
<li>Copy (Ctrl-C) the squares from my post or from unicode-table.com</li>
<li>In the Scrivener menubar go to “Project” -> “Meta-Data Settings” and then click on the “Status” tab. This is where you can add your own custom Labels and Statuses or arbitrary meta-data.</li>
<li>Hit the “+” button to add a new Status and paste (Ctrl-V) the special characters right there. The unicode numbers were just there for reference in case the graphics weren’t showing up properly on anybody’s computer.</li>
</ol>
<p><strong><a href="#106" title="2013-12-14 05:09:05">Chloe Carson</a>:</strong> Hey this is fantastic, thanks so much! I imagine I could use these on Squarespace as well.</p>
<p><strong><a href="#101" title="2013-11-27 13:07:31">ady coles</a>:</strong> Hi Chris, This is great! If you don’t mind, i would like to include a link to this article from my ‘scrivener resources’ page. (http://acol.es/stScrivener) Ady</p>
<p><strong><a href="#102" title="2013-11-27 13:33:22">Chris Lesage</a>:</strong> Hi Ady, yes please feel free. Thanks for the comment.</p>Maya Python: Reset Selected Controls2013-10-01T21:54:00-04:002013-10-01T21:54:00-04:00Chris Lesagetag:chrislesage.com,2013-10-01:/python/maya-python-reset-selected-controls/<p><img alt="Reset Selected Script" src="http://chrislesage.com/wp-content/uploads/2013/10/reset_selected_script.jpg"></p>
<p>I have a script snippet to share with you today. This is how I quickly reset all selected objects to 0,0,0,0,0,0,1,1,1 in translate, rotate and scale with the stroke of a hotkey command.</p>
<p><strong>This is fantastically useful when you are animating!</strong> But it’s also for riggers, modellers or anyone working in Maya. Softimage <span class="caps">XSI</span> has this feature built in (Ctrl-Shift-R), so I made a little snippet to do the same in …</p><p><img alt="Reset Selected Script" src="http://chrislesage.com/wp-content/uploads/2013/10/reset_selected_script.jpg"></p>
<p>I have a script snippet to share with you today. This is how I quickly reset all selected objects to 0,0,0,0,0,0,1,1,1 in translate, rotate and scale with the stroke of a hotkey command.</p>
<p><strong>This is fantastically useful when you are animating!</strong> But it’s also for riggers, modellers or anyone working in Maya. Softimage <span class="caps">XSI</span> has this feature built in (Ctrl-Shift-R), so I made a little snippet to do the same in Maya.</p>
<p>First I’ll show the simple code, explicitly written for each attribute. And then for the Python fans, I’ll show how to shorten it using List Comprehension because why not? After the scripts, I’ll explain a bit more how it works. <strong>If you just want the script, just copy/paste this and use it. If you want to geek out about List Comprehension and PyMEL, read on…</strong></p>
<h3>Reset Selected: The simple version</h3>
<div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">pymel.core</span> <span class="kn">as</span> <span class="nn">pm</span>
<span class="k">def</span> <span class="nf">reset_selected</span><span class="p">(</span><span class="n">oColl</span><span class="p">):</span>
<span class="k">for</span> <span class="n">oNode</span> <span class="ow">in</span> <span class="n">oColl</span><span class="p">:</span>
<span class="k">try</span><span class="p">:</span> <span class="n">oNode</span><span class="o">.</span><span class="n">tx</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="k">except</span><span class="p">:</span> <span class="k">pass</span>
<span class="k">try</span><span class="p">:</span> <span class="n">oNode</span><span class="o">.</span><span class="n">ty</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="k">except</span><span class="p">:</span> <span class="k">pass</span>
<span class="k">try</span><span class="p">:</span> <span class="n">oNode</span><span class="o">.</span><span class="n">tz</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="k">except</span><span class="p">:</span> <span class="k">pass</span>
<span class="k">try</span><span class="p">:</span> <span class="n">oNode</span><span class="o">.</span><span class="n">rx</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="k">except</span><span class="p">:</span> <span class="k">pass</span>
<span class="k">try</span><span class="p">:</span> <span class="n">oNode</span><span class="o">.</span><span class="n">ry</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="k">except</span><span class="p">:</span> <span class="k">pass</span>
<span class="k">try</span><span class="p">:</span> <span class="n">oNode</span><span class="o">.</span><span class="n">rz</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="k">except</span><span class="p">:</span> <span class="k">pass</span>
<span class="k">try</span><span class="p">:</span> <span class="n">oNode</span><span class="o">.</span><span class="n">sx</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="k">except</span><span class="p">:</span> <span class="k">pass</span>
<span class="k">try</span><span class="p">:</span> <span class="n">oNode</span><span class="o">.</span><span class="n">sy</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="k">except</span><span class="p">:</span> <span class="k">pass</span>
<span class="k">try</span><span class="p">:</span> <span class="n">oNode</span><span class="o">.</span><span class="n">sz</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="k">except</span><span class="p">:</span> <span class="k">pass</span>
<span class="n">runthescipt</span> <span class="o">=</span> <span class="n">pm</span><span class="o">.</span><span class="n">Callback</span><span class="p">(</span><span class="n">reset_selected</span><span class="p">,</span> <span class="n">pm</span><span class="o">.</span><span class="n">selected</span><span class="p">()</span> <span class="p">)</span>
<span class="n">runthescipt</span><span class="p">()</span>
</pre></div>
<h3>Reset Selected: The Fancy List Comprehension Version</h3>
<div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">pymel.core</span> <span class="kn">as</span> <span class="nn">pm</span>
<span class="k">def</span> <span class="nf">reset_selected</span><span class="p">(</span><span class="n">oColl</span><span class="p">):</span>
<span class="n">trList</span> <span class="o">=</span> <span class="p">[</span><span class="s1">'.tx'</span><span class="p">,</span><span class="s1">'.ty'</span><span class="p">,</span><span class="s1">'.tz'</span><span class="p">,</span><span class="s1">'.rx'</span><span class="p">,</span><span class="s1">'.ry'</span><span class="p">,</span><span class="s1">'.rz'</span><span class="p">]</span>
<span class="n">sList</span> <span class="o">=</span> <span class="p">[</span><span class="s1">'.sx'</span><span class="p">,</span><span class="s1">'.sy'</span><span class="p">,</span><span class="s1">'.sz'</span><span class="p">]</span>
<span class="c1"># o is each object, x is each attribute</span>
<span class="k">for</span> <span class="n">attr</span> <span class="ow">in</span> <span class="p">[(</span><span class="n">o</span><span class="p">,</span> <span class="n">x</span><span class="p">)</span> <span class="k">for</span> <span class="n">o</span> <span class="ow">in</span> <span class="n">oColl</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">trList</span><span class="p">]:</span>
<span class="k">try</span><span class="p">:</span> <span class="n">pm</span><span class="o">.</span><span class="n">Attribute</span><span class="p">(</span><span class="n">attr</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">attr</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="k">except</span><span class="p">:</span> <span class="k">pass</span>
<span class="k">for</span> <span class="n">attr</span> <span class="ow">in</span> <span class="p">[(</span><span class="n">o</span><span class="p">,</span> <span class="n">x</span><span class="p">)</span> <span class="k">for</span> <span class="n">o</span> <span class="ow">in</span> <span class="n">oColl</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">sList</span><span class="p">]:</span>
<span class="k">try</span><span class="p">:</span> <span class="n">pm</span><span class="o">.</span><span class="n">Attribute</span><span class="p">(</span><span class="n">attr</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">attr</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="k">except</span><span class="p">:</span> <span class="k">pass</span>
<span class="n">runthescipt</span> <span class="o">=</span> <span class="n">pm</span><span class="o">.</span><span class="n">Callback</span><span class="p">(</span><span class="n">reset_selected</span><span class="p">,</span> <span class="n">pm</span><span class="o">.</span><span class="n">selected</span><span class="p">()</span> <span class="p">)</span>
<span class="n">runthescipt</span><span class="p">()</span>
</pre></div>
<h3>Notes about this script:</h3>
<ul>
<li><strong>Fully supports undo and redo</strong>.</li>
<li>There are 2 scripts below. Grab either one. <strong>They do the same thing</strong>.</li>
<li>Set it to <strong><em>Ctrl-Shift-R</em></strong> in your Maya hotkey editor. Don’t forget to set the hotkey to Python.</li>
<li>I personally use PyMEL instead of maya.cmds because it can generate a list of object pointers rather than strings, so it is a lot easier to use from an <span class="caps">OOP</span> point of view. Some studios do not use PyMEL, so be aware of this.</li>
<li><strong>The pm.Callback() takes an argument</strong>, so instead of pm.selected() you could pass it a list of all your character rig controls, or all the locators in your scene, etc. etc.</li>
<li>Every iteration has a try/except on it, so that if your attribute is driven or locked the script will continue without failing.</li>
<li>You can also use makeIdentity() to quickly reset an object, but if some of your attributes are locked, this won’t work.</li>
</ul>
<h3>How list comprehension works:</h3>
<ul>
<li><a href="http://docs.python.org/2/tutorial/datastructures.html#list-comprehensions" title="List Comprehension documentation">List Comprehension</a> lets you build up lists quickly by using [x for x in y]</li>
<li>But you can also loop over two lists at once with one line:<br>
[(x + y) for x in (1,2,3) y in (4,5,6)]</li>
<li>This acts like a nested iterator which will add each of (1,2,3) with each of (4,5,6) resulting in 9 combinations. (1+4, 1+5, 1+6, 2+4, 2+5, and so on…)</li>
<li>I then take those two combined elements to gather all the transform attributes for all of my objects.</li>
</ul>
<h3>How pm.Attribute works:</h3>
<ul>
<li>I’m iterating over two lists with my list comprehension so I need to combine it again, casting it as a pm.Attribute( object name + attribute ).</li>
<li>However, if you were explicitly setting an attribute it would be as simple as yourObject.tx.set(0)</li>
<li>You could also create your attribute in the list comprehension, but if you try and run the script on a shape node that has no attributes, then the script will fail.</li>
<li>You could get around this by including a try/except function inside the list comprehension or by filtering your objects for transform nodes only, but that is just becoming too complex for this little script.</li>
</ul>
<h2>In Summary</h2>
<p>I use this hotkey all the time! I missed it from Softimage. Your animators are going to love using it too! Feel free to use it, and if you find bugs, improve it or rewrite it in <span class="caps">MEL</span> or maya.cmds let us know in the comments. Thanks!</p>
<hr>
<h2>Comments (closed)</h2>
<p><strong><a href="#86" title="2013-11-06 23:47:39">Markus Daum</a>:</strong> nice one! :) here’s a simple maya commands version… </p>
<div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">maya.cmds</span> <span class="kn">as</span> <span class="nn">mc</span>
<span class="n">attrVsDefaultValue</span> <span class="o">=</span> <span class="p">{</span><span class="s1">'sx'</span><span class="p">:</span><span class="mi">1</span><span class="p">,</span> <span class="s1">'sy'</span><span class="p">:</span><span class="mi">1</span><span class="p">,</span> <span class="s1">'sz'</span><span class="p">:</span><span class="mi">1</span><span class="p">,</span> <span class="s1">'rx'</span><span class="p">:</span><span class="mi">0</span><span class="p">,</span> <span class="s1">'ry'</span><span class="p">:</span><span class="mi">0</span><span class="p">,</span> <span class="s1">'rz'</span><span class="p">:</span><span class="mi">0</span><span class="p">,</span> <span class="s1">'tx'</span><span class="p">:</span><span class="mi">0</span><span class="p">,</span> <span class="s1">'ty'</span><span class="p">:</span><span class="mi">0</span><span class="p">,</span> <span class="s1">'tz'</span><span class="p">:</span><span class="mi">0</span><span class="p">}</span>
<span class="n">sel</span> <span class="o">=</span> <span class="n">mc</span><span class="o">.</span><span class="n">ls</span><span class="p">(</span><span class="n">sl</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
<span class="k">for</span> <span class="n">obj</span> <span class="ow">in</span> <span class="n">sel</span><span class="p">:</span>
<span class="k">for</span> <span class="n">attr</span> <span class="ow">in</span> <span class="n">attrVsDefaultValue</span><span class="p">:</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">mc</span><span class="o">.</span><span class="n">setAttr</span><span class="p">(</span><span class="s1">'</span><span class="si">%s</span><span class="s1">.</span><span class="si">%s</span><span class="s1">'</span><span class="o">%</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="n">attr</span><span class="p">),</span> <span class="n">attrVsDefaultValue</span><span class="p">[</span><span class="n">attr</span><span class="p">])</span>
<span class="k">except</span><span class="p">:</span>
<span class="k">pass</span>
</pre></div>
<p>Cheers! -Markus</p>
<p><strong><a href="#88" title="2013-11-07 13:50:38">Chris Lesage</a>:</strong> Thanks Markus! Your version also respects undo/redo. I’ll have to take a look at mine and remember why I used Callback. :) (Also, it looks like my comments don’t keep tabs in the formatting. I’ll see if I can sort that out. Fixed.)</p>The Fastest Way to Search API and Help Docs2013-09-24T20:21:00-04:002013-09-24T20:21:00-04:00Chris Lesagetag:chrislesage.com,2013-09-24:/rigging-tutorials/fastest-way-to-search-api-help-docs/<p>You probably frequently visit at least one or two <span class="caps">API</span> documentation, help docs or reference websites when you are programming or learning a new language or software. Firefox and Chrome have a trick to use a custom search keyword in the location bar to quickly navigate <span class="caps">API</span> docs or any other frequently searched sites. If you take a few minutes to set this up, it will save you a lot of time and keystrokes, I promise.</p>
<p><img src="http://chrislesage.com/wp-content/uploads/2013/09/custom-search-api.jpg" alt="custom-search-api" width="433" height="93" class="alignnone size-full wp-image-473" /></p>
<p>So for example, when …</p><p>You probably frequently visit at least one or two <span class="caps">API</span> documentation, help docs or reference websites when you are programming or learning a new language or software. Firefox and Chrome have a trick to use a custom search keyword in the location bar to quickly navigate <span class="caps">API</span> docs or any other frequently searched sites. If you take a few minutes to set this up, it will save you a lot of time and keystrokes, I promise.</p>
<p><img src="http://chrislesage.com/wp-content/uploads/2013/09/custom-search-api.jpg" alt="custom-search-api" width="433" height="93" class="alignnone size-full wp-image-473" /></p>
<p>So for example, when I want to search the Maya PyMEL docs, all I have to type is “pm setTransformation” in the location bar and Chrome brings me directly to the search results in the PyMEL documentation.</p>
<p>I don’t have to Google first. I don’t have to click a bookmark and then find the search box first. I just search and I’m there.</p>
<h2>Here’s how to set that up.</h2>
<p>First browse to your most frequently used help documentation and <strong>do a search for anything</strong>. You just want to be able to find the url of the search results so you can replace it with “%s”. </p>
<h3>Template <span class="caps">URL</span></h3>
<ol>
<li>http://yoursite/search.html?q= <strong style="color:red;">your_search_term</strong></li>
<li>http://yoursite/search.html?q=<strong style="color:red;">%s</strong> </li>
</ol>
<h3>Google Chrome</h3>
<ol>
<li><strong>Copy</strong> the url of your search</li>
<li><strong>change the search query to “%s”</strong> (examples below.)</li>
<li>In the <span class="caps">URL</span> bar, <strong>right click</strong> and click “<strong>Edit Search Engines…</strong>”</li>
<li>Under “<strong>Other Search Engines</strong>“, scroll to the bottom where you can enter your info.</li>
<li>Enter a <strong>name</strong>, a unique <strong>keyword</strong> to trigger the search and then <strong>your %s <span class="caps">URL</span></strong>.</li>
</ol>
<h3>Firefox</h3>
<ol>
<li><strong>Copy</strong> the url of your search</li>
<li><strong>change the search query to “%s”</strong> (examples below.)</li>
<li>Under “Bookmarks” click “<strong>Show All Bookmarks</strong>” or hit<strong> Ctrl-Shift-B</strong>.</li>
<li><strong>Right click</strong> in the bookmarks area and click “<strong>New Bookmark</strong>”</li>
<li>Enter a <strong>name</strong>, <strong>your %s <span class="caps">URL</span></strong>, optional tags, and a <strong>keyword</strong> to trigger the search.</li>
</ol>
<h2>Some examples for the search term “matrix”:</h2>
<h3>Unity3D Scripting Reference</h3>
<ul>
<li>http://docs.unity3d.com/Documentation/ScriptReference/30_search.html?q=<strong style="color:red;">matrix</strong></li>
<li>http://docs.unity3d.com/Documentation/ScriptReference/30_search.html?q=<strong style="color:red;">%s</strong></li>
<li><strong>keyword:</strong> assign a unique keyword or acronym. Just don’t pick a word you would use in a regular search: Perhaps “un” for Unity3D.</li>
</ul>
<h3>Maya PyMEL</h3>
<ul>
<li>http://download.autodesk.com/global/docs/maya2014/en_us/PyMel/search.html?q=<strong style="color:red;">matrix</strong>&check_keywords=yes&area=default</li>
<li>http://download.autodesk.com/global/docs/maya2014/en_us/PyMel/search.html?q=<strong style="color:red;">%s</strong>&check_keywords=yes&area=default</li>
<li><strong>keyword:</strong> I use “pm” for PyMEL</li>
</ul>
<h3>Stack Overflow</h3>
<ul>
<li>http://stackoverflow.com/search?q=<strong style="color:red;">matrix</strong></li>
<li>http://stackoverflow.com/search?q=<strong style="color:red;">%s</strong></li>
<li><strong>keyword:</strong> “sto” for Stack Overflow (the keyword isn’t triggered until you hit spacebar, so you would still be able to type “storage” for example, and you still have the option to search Google for “sto foobar” if you click down twice.)</li>
</ul>
<h3>Google Groups</h3>
<ul>
<li>https://groups.google.com/forum/#!search/<strong style="color:red;">matrix</strong></li>
<li>https://groups.google.com/forum/#!search/<strong style="color:red;">%s</strong></li>
<li><strong>keyword:</strong> “gg” for Google Groups. Whatever is easy for you to remember.</li>
</ul>
<h2>In Summary…</h2>
<p>Now you type your keyword followed by whatever you want to search for and it will directly bring you to the search results on that page. (And once you are on the page, don’t forget the Ctrl-F hotkey!) This will make you look like a fast-browsing maniac to anyone watching over your shoulder.</p>
<hr>
<h2>Comments (closed)</h2>
<p><strong><a href="#79" title="2013-09-27 14:08:49">Sune</a>:</strong> Nice one! Alas this does not seem to work for any of the autodesk native online documentation</p>
<p><strong><a href="#80" title="2013-09-27 14:38:07">Chris Lesage</a>:</strong> Sune, that is true because they use frames. But you can try this tip from Benedict Apuna and use a mix of Custom Search + Google Site Search: Add “site:” to the front and put a space between %s. Don’t forget to remove the final “whatever.html” from your template url. <strong>Maya <span class="caps">API</span>:</strong> “site:docs.autodesk.com/<span class="caps">MAYAUL</span>/2013/<span class="caps">ENU</span>/Maya-<span class="caps">API</span>-Documentation <strong>%s</strong>”</p>
<p><strong><a href="#81" title="2013-09-27 15:04:19">Tyler Hurd</a>:</strong> Awesome. Wish I had known about this years ago.</p>
<p><strong><a href="#83" title="2013-09-29 08:57:41">Mayur</a>:</strong> very nice trick thanks a lot !!</p>A New Demoreel & My Cartoony Face Rig Structure2013-09-09T15:11:00-04:002013-09-09T15:11:00-04:00Chris Lesagetag:chrislesage.com,2013-09-09:/character-rigging/new-demoreel-and-face-rig-structure/<p>I just got back from an awesome summer vacation, travelling in South America! Now I’m back to work, developing some new Python animation tools and plugins (which I’ll blog about soon) and looking for new clients and projects for the coming year! Today I want to show you my new character rigging demoreel. It has a few highlights of my tech artist work from this past year. After the video, you’ll read a bit about the facial …</p><p>I just got back from an awesome summer vacation, travelling in South America! Now I’m back to work, developing some new Python animation tools and plugins (which I’ll blog about soon) and looking for new clients and projects for the coming year! Today I want to show you my new character rigging demoreel. It has a few highlights of my tech artist work from this past year. After the video, you’ll read a bit about the facial rig that I developed with help from Rigging Dojo for a cartoon feature film.</p>
<p><strong>In this demoreel:</strong></p>
<ul>
<li>Character rigging for Ember Lab’s successfully Kickstarter-funded indie film, <a href="http://www.dustthefilm.com/">Dust</a></li>
<li>Cartoony face rigging for an animated feature film</li>
<li>Cinematics from a Coca-Cola mobile game I worked on (I also did some in-game rigs for a Maya/Unity workflow.)</li>
<li>Some rigging goodies like the cylindrical foot-roll I blogged about, and an auto-swinging trunk/tail rig.</li>
<li>Some footage from some mobile game prototypes I’m developing in Corona and Unity3D.</li>
</ul>
<iframe width="560" height="315" src="//www.youtube.com/embed/lBV4AaugXG4?rel=0" frameborder="0" allowfullscreen></iframe>
<h3>The “Face Plates” Rig</h3>
<p>The cartoony face rig I developed was really interesting. I based it off of some of the principles from “<a href="https://disney-animation.s3.amazonaws.com/uploads/production/publication_asset/52/asset/hybridFacialTalk.pdf">A Hybrid Approach to Facial Rigging</a>“. And I took a session of <a href="http://riggingdojo.com">Rigging Dojo</a> where Brad Clark and the Dojo community really helped me push the quality of the rig.</p>
<p>The face rig needed to be flexible and expressive, but it also needed to be fast to setup and swap between characters. There was a large cast of characters, and I started the project alone. Eventually we hired a second rigger, but the process had to be modular and stream-lined. In the past, my face rigs would have used dozens of blendshapes, based on Stop Staring. But in this production we had a <span class="caps">LOT</span> of modelling revisions, client feedback and a small team!</p>
<h3>The process had to be simple and fast.</h3>
<p>So we had to have a solution that didn’t have a lot of brute-force work for each character, such as requiring too many corrective blendshapes which would have to be re-done or tweaked with each modelling revision. I kept the amount of blendshapes down to only 8-10 per character, for special things like puckering and “ewww” shapes. My solution was something I called “Face Plates”. Using a series of nurbs surfaces which are shaped to match the curvature of the character’s face.</p>
<p><img alt="face_rig_face_plates1" src="http://chrislesage.com/wp-content/uploads/2013/09/face_rig_face_plates1.jpg"></p>
<p>The curvature of the plate is controlled by two blendshapes. By combining the two shapes, they can be concave, convex or saddle-shaped. Using follicles and geometry-based constraints, a joint follows the curvature of the nurbs, giving an effect of sliding over a rounded structure.</p>
<p><img alt="face_plates_curve" src="http://chrislesage.com/wp-content/uploads/2013/09/face_plates_curve.gif"></p>
<p>The animator uses the controller in X and Y, and you get a nice natural curved effect with less effort. Using the controller in Z lets you pull the skin off of the surface if you need to.</p>
<p><img alt="face_rig_face_plates2" src="http://chrislesage.com/wp-content/uploads/2013/09/face_rig_face_plates2.jpg"></p>
<h3>The advantages I found with this system…</h3>
<p>You could also use a single object like in the “Hybrid Approach to Facial Rigging”. But by having separate pieces, you have a few advantages:</p>
<ol>
<li>Place them to match the face in a fairly complex way very quickly with only a few parameters and without having to do any modelling. </li>
<li>Constrain the plates to the rig controllers or add Driven Keys for an additional layer of complexity/expression. </li>
<li>Have 1 controller moving concave while a nearby one moves convex for creating overlapping or fat-bulging effects with only standard skinning. </li>
<li>Easily make or remove plates to create a custom character. In this way we were able to use the same basic rig to also rig cartoony animals with completely different proportions. </li>
<li>The size of the plates gives your joints a natural limit, preventing the animators from breaking model. </li>
</ol>
<h3>A Simple Skin-Based Method for Fast Setup</h3>
<p>But the best thing about this approach is the simplicity of the skinning. By using joints to skin the face, when the clients asked for modelling revisions, it was simply a matter of adjusting the positions of the Face Plates, and then transferring the weights to the new geometry without too much pain and re-modelling of blendshapes. This also made it fast and easy to setup new characters. Animation could even be swapped between characters, though it would take some tweaking afterwards. (In the future I’d like to figure out how to re-target the animation. The translation, scale and curvature of the plates holds information about the characters proportions.)</p>
<p>I then set up a face panel which controls large expressive motions on the face for quickly blocking out poses. And then the controllers on the face allow the animators to make more fine-tuned adjustments. Again, 90% of the face rig is done through placing the Face Plates and using regular skinning. Other than that, the head squash-and-stretch uses a lattice.</p>
<p>Do you have any questions or feedback? Do you have any favourite examples of face rigging systems? Share them in the comments.</p>
<hr>
<h2>Comments (closed)</h2>
<p><strong><a href="#77" title="2013-09-13 16:05:26">Chris Lesage</a>:</strong> Great link, thanks Jamie! I had the .mp3 of this talk from <span class="caps">GDC</span>, but this is much better.</p>
<p><strong><a href="#73" title="2013-09-09 19:49:39">Jason Campbell</a>:</strong> This looks like a really strong and flexible system. Are the plate blendshapes used to speed up the initial setup in matching the model curvature or are they driven by the controllers in posing to modify the underlying geometry? Dare I hope for a full tutorial sometime in the future? Thanks, J.</p>
<p><strong><a href="#74" title="2013-09-09 20:39:05">Chris Lesage</a>:</strong> Hi Jason, They are just to speed up the setup. I connect the blendshapes via 2 parameters in the channel box of the nurbs surface, so I can quickly translate and curve it without fussing with the blendshape node. Our characters were nice and round, so these 2 shapes were good enough to match the geometry. Using the curvature to drive the geometry is an interesting idea though! I’d be happy to write about this more in depth later on. There are some other tricks I didn’t mention, like using 2 joints for each controller, one that doesn’t follow the Z-translation of the controller. So for example you can have a nice round shaped cheek bulge when you pull in Z on one joint, but include a wider, softer influence on the other joint which could give you nice soft motion up near the eyes when moving the cheek in X and Y. (That might not make any sense without a picture or a video! )</p>
<p><strong><a href="#75" title="2013-09-12 07:30:37">Debster</a>:</strong> You are awesome. <3</p>
<p><strong><a href="#76" title="2013-09-13 09:37:31">Jamie</a>:</strong> Cool bro! good to see someone else also using nurbs surfaces for sliding joints.. I’ve been using this trick for a few years for face rigs.. I like to call it High Fidelity Facial Rigging.. I just place all the surfaces I want and run a script to setup everything.. but I got the idea originally from David Hunt from Bungie.. in a publication ‘Modular Procedural Rigging’ on their website.. http://halo.bungie.net/inside/publications.aspx check it out.. some really cool stuff in there.. Good work mate! Jamie</p>
<p><strong><a href="#203" title="2014-06-06 08:39:51">Marley Kudiabor</a>:</strong> Hello Chris, I recently have been doing nothing but this setup and wanted to know if you are still using it at all or if you have transitioned into any other interesting setups. I have used this setup almost exclusively and it works great especially for closing large almond shaped almost “anime” style eyes if you use spheres and love it, I also used it for a realistic character and it worked out great there as well. I just wanted to know if you had any other setups to share. Many thanks</p>
<p><strong><a href="#204" title="2014-06-06 13:43:32">Chris Lesage</a>:</strong> Hey Marley. I’m working mostly on props and Python tools this year, so I’ve only done a few faces. Glad you enjoy the setup. Cheers!</p>
<p><strong><a href="#256" title="2014-10-17 19:15:21">sufiyan</a>:</strong> Hi Chris, I’m seeking tips and tricks on particular scene in which I’m rigging a bear who is literary going to strip off his upper fur skin like any jacket or coat. So bit concerned about how to approach it. Please do you have any suggestions or idea for this. Let me know… Thanking you…</p>
<p><strong><a href="#257" title="2014-10-17 19:23:19">Chris Lesage</a>:</strong> haha, gross! When you are trying to solve complex deformations like this, sometimes it helps to consider it in layers. So for example, could you make a version of the face that is flattened out in 2D, and then create a peeling effect on that flat face? <span class="caps">THEN</span>, you could create a blend shape or a deformer that wraps the flat face onto the 3D shape of the face. That might not work specifically. But the main idea is to think of it in layers if you can. Put the most complex deformation on the most simple geometry that you can define, and then deform the simple geometry into a more complex shape. Does that give you any ideas? I’d love to see what you come up with.</p>
<p><strong><a href="#260" title="2014-10-18 19:24:13">sufiyan</a>:</strong> Hi again, I appreciate your suggestion and tips. The idea of flattened faces is seeming to be little workable in which I might wrap simplified mesh with original mesh but in my scene he is going to roll the cloth after striping off as well as I was planning to use proxy rig set up within same bear rig for upper furry skin or else could make separate version of rig for furry skin and combine it scene…but both method will gonna hectic and challenging, however thank you for your feed back…</p>
<p><strong><a href="#261" title="2014-10-18 19:29:27">sufiyan</a>:</strong> One more thing how it would be if I use sticky lips kind deformer for opening part of furry skin…will it be fine for this…</p>Manually Create a Single Maya Follicle in Python2013-02-22T00:00:00-05:002013-02-22T00:00:00-05:00Chris Lesagetag:chrislesage.com,2013-02-22:/character-rigging/manually-create-maya-follicle-in-python/<p>Do you use Maya follicles to pin objects to your geometry? Are you still doing it the old way, by creating a Hair System and then deleting all the parts you don’t need? Below I’ll share my simple Maya Python script that creates and pins a single follicle onto a nurbs surface. (<a href="#folliclescript">Jump straight to the script.</a>)</p>
<p>I love using follicles. They adhere to a nurbs or poly surface and they maintain a good, predictable orientation in normal …</p><p>Do you use Maya follicles to pin objects to your geometry? Are you still doing it the old way, by creating a Hair System and then deleting all the parts you don’t need? Below I’ll share my simple Maya Python script that creates and pins a single follicle onto a nurbs surface. (<a href="#folliclescript">Jump straight to the script.</a>)</p>
<p>I love using follicles. They adhere to a nurbs or poly surface and they maintain a good, predictable orientation in normal and tangent space, which means they don’t shift or rotate and they don’t need additional up-vector constraints. It is a great and predictable way to pin things to your geometry.</p>
<h2>How you can use follicles:</h2>
<ul>
<li>Create a flip-free “Ribbon <span class="caps">IK</span>” for spines, tentacles or cartoon limbs without needing a ton of up-vector constraints!</li>
<li>Attach a boat to a flowing water surface</li>
<li>Rivet buttons or patches onto clothing</li>
<li>Rivet some controllers to one layer of your character, so you can adjust a second layer. (Imagine a character with a scarf around their neck.)</li>
<li>Slide facial controls along an underlying “skull” object or create other skin sliding effects.</li>
<li>Measure the distance between two points (even if there is no vertex where you want to measure) on geometry, even if is being deformed in many different ways.</li>
<li>Arvid Schneider’s video shows us how we can use follicles as a great way to pin things to different types of meshes <a href="http://lesterbanks.com/2012/08/using-maya-hair-follicles-for-parenting-constraining-geometry-to-a-surface/">http://lesterbanks.com/2012/08/using-maya-hair-follicles-for-parenting-constraining-geometry-to-a-surface/</a></li>
</ul>
<p>In the past, I would create the follicles by creating a hair system and then delete everything except the follicles. When I went to script this, I found it was difficult to access the hair system with Python and PyMEL. So instead I wrote this PyMEL snippet which lets you create a single follicle manually. It sets up all the same connections but the hair system never gets created. (I am only supporting nurbs surfaces in this script, because if you use polygons, you need to have UVs on the mesh, and the follicle will act unpredictably depending on how clean your UVs are.) </p>
<h2>Setting Things Up</h2>
<p>Before we get to the script, I just want to point out how I use this. I <strong>never</strong> pin follicles directly on to my polygon characters. Why?</p>
<ul>
<li>Because if your geometry changes, you have to disconnect and then reconnect everything</li>
<li>If the UVs get changed, the position of the follicle will change. If your UVs aren’t clean, predicting where the follicle will travel is nearly impossible.</li>
<li>By using nurbs, you have a nice clean 0 to 1 <span class="caps">UV</span> space, which is nice and easy for setting up Driven Keys or distributing multiple follicles in an even row. (Plus you know that 0.5 is precisely the middle.)</li>
</ul>
<p>So what I do instead is this:</p>
<p><img alt="using_nurbs_for_follicle_placement" src="http://chrislesage.com/wp-content/uploads/2013/02/using_nurbs_for_follicle_placement-e1382696561574-286x300.jpg"></p>
<ol>
<li>create a small nurbs plane, big enough that will cover the area I want to work with.</li>
<li>give it 2-6 patches, depending on how much it will have to deform. (2 often works.)</li>
<li>Bend it and place it so it roughly matches the shape of your character’s geometry.</li>
<li>Skin it with the same joints as your character and copy weights. (If you have any other deformers or blendshapes, you will need to match those too.) This way you can safely and easily change your character’s geometry without losing all your follicle work. (This is a common occurrence in production. Never assume your geometry is final.)<a id="folliclescript"></a></li>
</ol>
<h2>Here is the script</h2>
<div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">pymel.core</span> <span class="kn">as</span> <span class="nn">pm</span>
<span class="k">def</span> <span class="nf">create_follicle</span><span class="p">(</span><span class="n">oNurbs</span><span class="p">,</span> <span class="n">uPos</span><span class="o">=</span><span class="mf">0.0</span><span class="p">,</span> <span class="n">vPos</span><span class="o">=</span><span class="mf">0.0</span><span class="p">):</span>
<span class="c1"># manually place and connect a follicle onto a nurbs surface.</span>
<span class="k">if</span> <span class="n">oNurbs</span><span class="o">.</span><span class="n">type</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'transform'</span><span class="p">:</span>
<span class="n">oNurbs</span> <span class="o">=</span> <span class="n">oNurbs</span><span class="o">.</span><span class="n">getShape</span><span class="p">()</span>
<span class="k">elif</span> <span class="n">oNurbs</span><span class="o">.</span><span class="n">type</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'nurbsSurface'</span><span class="p">:</span>
<span class="k">pass</span>
<span class="k">else</span><span class="p">:</span>
<span class="s1">'Warning: Input must be a nurbs surface.'</span>
<span class="k">return</span> <span class="bp">False</span>
<span class="c1"># create a name with frame padding</span>
<span class="n">pName</span> <span class="o">=</span> <span class="s1">'_'</span><span class="o">.</span><span class="n">join</span><span class="p">((</span><span class="n">oNurbs</span><span class="o">.</span><span class="n">name</span><span class="p">(),</span><span class="s1">'follicle'</span><span class="p">,</span><span class="s1">'#'</span><span class="o">.</span><span class="n">zfill</span><span class="p">(</span><span class="mi">2</span><span class="p">)))</span>
<span class="n">oFoll</span> <span class="o">=</span> <span class="n">pm</span><span class="o">.</span><span class="n">createNode</span><span class="p">(</span><span class="s1">'follicle'</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="n">pName</span><span class="p">)</span>
<span class="n">oNurbs</span><span class="o">.</span><span class="n">local</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="n">oFoll</span><span class="o">.</span><span class="n">inputSurface</span><span class="p">)</span>
<span class="c1"># if using a polygon mesh, use this line instead.</span>
<span class="c1"># (The polygons will need to have UVs in order to work.)</span>
<span class="c1">#oMesh.outMesh.connect(oFoll.inMesh)</span>
<span class="n">oNurbs</span><span class="o">.</span><span class="n">worldMatrix</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="n">oFoll</span><span class="o">.</span><span class="n">inputWorldMatrix</span><span class="p">)</span>
<span class="n">oFoll</span><span class="o">.</span><span class="n">outRotate</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="n">oFoll</span><span class="o">.</span><span class="n">getParent</span><span class="p">()</span><span class="o">.</span><span class="n">rotate</span><span class="p">)</span>
<span class="n">oFoll</span><span class="o">.</span><span class="n">outTranslate</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="n">oFoll</span><span class="o">.</span><span class="n">getParent</span><span class="p">()</span><span class="o">.</span><span class="n">translate</span><span class="p">)</span>
<span class="n">oFoll</span><span class="o">.</span><span class="n">parameterU</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="n">uPos</span><span class="p">)</span>
<span class="n">oFoll</span><span class="o">.</span><span class="n">parameterV</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="n">vPos</span><span class="p">)</span>
<span class="n">oFoll</span><span class="o">.</span><span class="n">getParent</span><span class="p">()</span><span class="o">.</span><span class="n">t</span><span class="o">.</span><span class="n">lock</span><span class="p">()</span>
<span class="n">oFoll</span><span class="o">.</span><span class="n">getParent</span><span class="p">()</span><span class="o">.</span><span class="n">r</span><span class="o">.</span><span class="n">lock</span><span class="p">()</span>
<span class="k">return</span> <span class="n">oFoll</span>
</pre></div>
<p><strong>Important:</strong> To use the script, select a nurbs surface in Maya and run this line. Set the U and V parameters as you wish:</p>
<div class="highlight"><pre><span></span><span class="n">oFoll</span> <span class="o">=</span> <span class="n">create_follicle</span><span class="p">(</span><span class="n">pm</span><span class="o">.</span><span class="n">selected</span><span class="p">()[</span><span class="mi">0</span><span class="p">],</span> <span class="mf">0.5</span><span class="p">,</span> <span class="mf">0.5</span><span class="p">)</span>
</pre></div>
<p>If you want to create a bunch of follicles evenly spread along a long nurbs plane, use something like this:</p>
<div class="highlight"><pre><span></span><span class="n">myObject</span> <span class="o">=</span> <span class="n">pm</span><span class="o">.</span><span class="n">selected</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span>
<span class="n">howManyFollicles</span> <span class="o">=</span> <span class="mi">8</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="n">howMany</span><span class="p">):</span>
<span class="n">oFoll</span> <span class="o">=</span> <span class="n">create_follicle</span><span class="p">(</span><span class="n">myObject</span><span class="p">,</span> <span class="n">i</span><span class="o">/</span><span class="p">(</span><span class="n">howManyFollicles</span><span class="o">-</span><span class="mf">1.00</span><span class="p">),</span> <span class="mf">0.5</span><span class="p">)</span>
</pre></div>
<h2>Thanks For Reading</h2>
<p>Share in the comments if you have used follicles to solve your rigging or animation problems!</p>
<hr>
<h2>Comments (closed)</h2>
<p><strong><a href="#64" title="2013-02-26 13:09:00">Chris Lesage</a>:</strong> Hi Marco, Thanks. Some of the rivet plugins I’ve seen come with very nice features too. I’ve used hundreds of follicles in some rigs (for a long tentacled creature for example) and I’ve found that by bypassing the Hair System I don’t see any significant performance hit. And all of the extra attributes associated with hair can be deleted since they aren’t connected to anything. (except U and V.)</p>
<p><strong><a href="#63" title="2013-02-26 07:49:44">Marco Giordano</a>:</strong> Well done sir! But If I can I never use follicles , follicles comes with a crazy loads of features from hair system which require extra computation , of course It all depends how many you need but 99% of the time I use custom rivets I wrote both for mesh and nurbs surface so I am sure It s only doing the task is supposed to. But again well done the script is really userfull for people that cannot rely on plugins</p>
<p><strong><a href="#67" title="2013-05-06 23:24:48">Chris Lesage</a>:</strong> Thanks Brad! I had never noticed the Popup Menus option there! That is a nice way to quickly build up some flexible menus, without getting into designing a little <span class="caps">UI</span> or popup dialog.</p>
<p><strong><a href="#66" title="2013-05-02 03:14:58">Brad Clark</a>:</strong> This is a great little script and a perfect tool to use this shelf #rigtip with. I took the code, added a double click to run the single follicles build and then added some right click options to add diffrent set of follicles to selected surface. https://vimeo.com/45485411 Thanks for the script Chris, Hope you are well.</p>How To Stop Collapsing Vertices in Maya Post Normalization2012-05-14T16:52:00-04:002012-05-14T16:52:00-04:00Chris Lesagetag:chrislesage.com,2012-05-14:/character-rigging/how-to-stop-collapsing-vertices-in-maya-post-normalization/<p><img alt="<img src=" src="http://chrislesage.com/wp-content/uploads/2012/05/collapsed_vertices.jpg"></p>
<p>So this is annoying. You are trying to paint weights in Maya using Post Normalization and a bunch of your vertices are collapsing to the origin! <strong>What’s going on!?</strong></p>
<p>Don’t fret. There is a simple explanation and an easy fix for this. But first, let’s look at what Post skinning is doing: </p>
<h3><span class="dquo">“</span>What is this Post Normalization skinning all about?”</h3>
<p>When using Post Normalization skinning for the first time, it can be a bit tricky to figure …</p><p><img alt="<img src=" src="http://chrislesage.com/wp-content/uploads/2012/05/collapsed_vertices.jpg"></p>
<p>So this is annoying. You are trying to paint weights in Maya using Post Normalization and a bunch of your vertices are collapsing to the origin! <strong>What’s going on!?</strong></p>
<p>Don’t fret. There is a simple explanation and an easy fix for this. But first, let’s look at what Post skinning is doing: </p>
<h3><span class="dquo">“</span>What is this Post Normalization skinning all about?”</h3>
<p>When using Post Normalization skinning for the first time, it can be a bit tricky to figure out how things are working. Basically Maya is taking the total of all the weights and then normalizing it to 1.0. With classic interactive skinning this is done <em>while you paint</em>, which means if you paint on <strong>Influence A</strong>, Maya automatically steals weights away from <strong>Influence B</strong> and <strong>Influence C</strong>.</p>
<p>If you are <strong>subtracting weights</strong>, it automatically tries to add weights to other joints. This can be very buggy and throw weights unpredictably.</p>
<p>With Post Normalization, Maya is keeping all the weights you’ve painted and doing this calculation on the fly. It stores the values of your weights <strong>without changing any of the others</strong>. You can paint all the way up to 1.0 on Influence A, Influence B and Influence C. Maya averages it out and the final effect is 0.333 on all 3 influences, but the weights are still painted to 1.0. This can be a great way to think of your weights as separate layers. <strong>It’s like a bunch of overlapping venn diagrams</strong>. </p>
<h3><span class="dquo">“</span>So what is happening in that ugly image?”</h3>
<p>What you are seeing is essentially a divide-by-zero error. When you first encounter these collapsing vertices, you might think it is a bug and dismiss Post Normalization as garbage or confusing. But it has a simple explanation. Since Maya isn’t automatically changing any weights, if you can paint all the weights to 1, you can also paint them all to 0. Maya is trying to calculate the totals of the weights but when there are no weights to divvy up, it simply can’t make the calculation.</p>
<h3>How To Fix It</h3>
<p>Luckily there is an easy fix. What I do is create an extra joint called “base_influence” and place it anywhere in the middle of my character or at origin. Next, flood the entire character geometry with 0.05 weight on “base_influence”.</p>
<p>Now you can paint the rest of your joints freely, but this one will always hold a tiny little bit of weight to prevent collapsing. Lastly, don’t forget to constrain this “base_influence” to your characters root joint or root controller so it follows when you move the character. </p>
<h3><span class="dquo">“</span>Why use it if it is so confusing?”</h3>
<p>It took me a while to get used to, but I use Post Normalization skinning all the time now. You get to think in layers. Smoothing and subtracting weights is bug-free. You just have to get used to the fact that if you are painting Influence A, you have to manually paint away any overlapping influence on Influence B, or you will never reach full influence.</p>
<h3>Another Alternative</h3>
<p>I haven’t had time to test this tool out yet. If you are interested in advanced skinning techniques and painting in layers, this sounds like a promising tool worth checking out: <a href="http://www.ngskintools.com/">ngSkin Tools</a> developed by Viktoras Makauskas. It sounds like Viktoras is developing something which solves a lot of the common frustrations with a Maya skinning workflow. It also uses regular skinning nodes, so it can also be a solution to video game riggers if Post Normalization isn’t an option for your engine.</p>
<p>If you have any skinning tricks and techniques, please let me know in the comments or share your wisdom on <a href="http://twitter.com/chrislesage">Twitter</a> with the #rigtip hashtag.</p>
<hr>
<h2>Comments (closed)</h2>
<p><strong><a href="#65" title="2013-03-01 07:31:10">Alex Bone</a>:</strong> thank you so much, this is great advice</p>Using a Unit Vector to Make a Cylindrical Foot Roll2012-04-03T02:42:00-04:002012-04-03T02:42:00-04:00Chris Lesagetag:chrislesage.com,2012-04-03:/character-rigging/using-a-unit-vector-to-make-a-cylindrical-foot-roll/<p>Here is a tutorial that will demonstrate how to use a Unit Vector to animate the pivot point of a cylinder so that the cylinder will roll on its bottom edge in any direction. I’m using this technique for the feet of my <a href="http://chrislesage.com/series/making-of-mini-mammoth/">Mini Mammoth rig</a>, but it could also be useful for robot feet, or adapted into different shapes for a variety of uses.</p>
<p>Here is a video of the foot rolling effect we are going to create …</p><p>Here is a tutorial that will demonstrate how to use a Unit Vector to animate the pivot point of a cylinder so that the cylinder will roll on its bottom edge in any direction. I’m using this technique for the feet of my <a href="http://chrislesage.com/series/making-of-mini-mammoth/">Mini Mammoth rig</a>, but it could also be useful for robot feet, or adapted into different shapes for a variety of uses.</p>
<p>Here is a video of the foot rolling effect we are going to create:</p>
<iframe width="560" height="315" src="http://www.youtube.com/embed/aSecO4KFjNw" frameborder="0" allowfullscreen></iframe>
<p><strong>Note: Be aware that my expression syntax may or may not play nicely with the html formatting you see, depending on how you are viewing this post. I have included a Maya 2012 scene file at the bottom of this post so you can download it and follow along. The final expression is included as a text file.</strong></p>
<p><strong>Notes about this tutorial:</strong></p>
<ul>
<li>I am using locators as vectors so we can see what is going on. Once we are done prototyping this as an expression we can transform it into node connections that work directly with the attribute data rather than a daisy-chain of connected locators. This tutorial will just show the expression so you can get the idea.</li>
<li>The order of the lines in your expression matters. Specifically, the foot’s rotation attributes will have to be animated before the pivots are translated in the expression. Otherwise I’ve found that you will sometimes get strange results. If your animation seems to jump or skip, keep this in mind.</li>
<li>For simplicity, the way I build this ignores rotation in Y. Instead when I go to integrate this into a real rig, I’ll group this entire foot roll rig underneath a parent node and use that to rotate in Y in global space.</li>
<li>The next step you could take would be to project the vector onto a curve using a closestPoint constraint. Shape the curve to match your character’s foot, and now you can have a foot roll in any shape you want!</li>
</ul>
<h3>So let’s get started</h3>
<ol>
<li>Create a cylinder with a radius of 5 and move it up so that it rests at the ground plane.</li>
<li>Create a joint at the bottom of the cylinder. Group the joint and call the group “foot_pivot”. The group will be controlled by the expression. Skin the cylinder to the joint.</li>
<li>Create a “foot_roll” controller. This can be a locator or a curve icon or whatever. This is the controller that will rotate the foot.<br>
<img alt="cylinder roll step 1 to 3" src="http://chrislesage.com/wp-content/uploads/2012/04/cylinder_roll_step1-3.jpg"></li>
<li>Create two locators. Name the first one “vector1” and the second one “normalized_vector1”.</li>
<li>Select the “foot_pivot” group. Go into Edit -> Channel Control and in the Nonkeyable Hidden column make the following visible and keyable:
<pre>
Rotate Pivot X, Rotate Pivot Y, Rotate Pivot Z
Rotate Pivot Translate X, Rotate Pivot Translate Y, Rotate Pivot Translate Z
</pre>
<img alt="cylinder roll step 5" src="http://chrislesage.com/wp-content/uploads/2012/03/cylinder_roll_step5.jpg"></li>
<li>The first step is to turn the rotation of the “foot_roll” control into <span class="caps">XZ</span> translation which we will feed into the pivot point of “foot_pivot”.
<pre>
vector1.translateX = -foot_pivot.rotateZ;
vector1.translateZ = foot_pivot.rotateX;
// (note the negative value. This may change for you depending
// on your controllers orientation.)
</pre>
<img alt="animated vector" src="http://chrislesage.com/wp-content/uploads/2012/03/anim_vector.gif">
<br>When you rotate the “foot_roll” now “vector1” will travel along the ground plane pointing in the direction of the rotation. But the distance from the foot is wrong and it is not in a circular shape. So…</li>
<li>We arrive at the meat of this entire tutorial. To get a useful pivot we need to create a <strong>Unit Vector</strong> or a normalized vector which will always have the same length of 1 no matter which direction it is pointing.<br><br>If you aren’t familiar with vectors, this would be the same as having a 1-bone <span class="caps">IK</span> chain. As you move the effector around, the chain points in the correct direction, but stays the same length.<br><br>However, if you aren’t familiar with vectors, I highly suggest learning about them. They will open up a new world of ideas for you as a rigger or <span class="caps">TD</span>.
<a href="http://www.rtrowbridge.com/blog/2012/03/442/">http://www.rtrowbridge.com/blog/2012/03/442/</a>
<img alt="unit vectors ahoy" src="http://chrislesage.com/wp-content/uploads/2012/03/unit_vectors_ahoy.jpg">
<br>We’ll use the built-in unit() vector function in the Expression Editor. Later if you want to rebuild it with nodes, you can get the same functionality with the vectorProduct node and turning “Normalize output” to <span class="caps">ON</span>.
<pre>
vector $norm = unit(<<vector1.translateX,vector1.translateY,vector1.translateZ>>);
</pre></li>
<li>Now we have a vector, so let’s drive the “normalized_vector” locator so we can see what it is doing. (We don’t need to use the Y-component.)
<pre>
normalized_vector1.translateX = $norm.x
normalized_vector1.translateZ = $norm.z
</pre></li>
<li>Ok, but now the problem is that our foot radius is 5 units and the Unit Vector is only 1 unit long. So let’s create a variable to multiply the unit vector which will be easy to edit if we need to use it on different sized cylinders. We add the following to the expression:
<pre>
float $radius = 5.0;
normalized_vector1.translateX = $norm.x * $radius;
normalized_vector1.translateZ = $norm.z * $radius;
</pre>
Now the “normalized_vector1” should be travelling in a circle around our foot as we rotate “foot_roll”.</li>
<li>Now this normalized vector is just for visualization or debugging purposes. Let’s connect that straight into the rotatePivotX and rotatePivotZ attributes of the “foot_pivot”. (the group that parents the foot joint.)
<pre>
foot_pivot.rotatePivotX = $norm.x * $radius;
foot_pivot.rotatePivotZ = $norm.z * $radius;
</pre></li>
<li>And finally, rotate the “foot_pivot”. (Note that this will go at the top of the expression. Putting it at the bottom caused erratic behaviour for me.)
<pre>
foot_pivot.rotateX = foot_roll.rotateX;
foot_pivot.rotateY = 0;
foot_pivot.rotateZ = foot_roll.rotateZ;
</pre></li>
</ol>
<h3>Bring it all together and this is our final expression:</h3>
<pre>
// Rotate the pivot_rotator to match the controller
foot_pivot.rotateX = foot_roll.rotateX;
foot_pivot.rotateY = 0;
foot_pivot.rotateZ = foot_roll.rotateZ;
float $radius = 5.0;
// Turn the controller rotation into XZ translation
vector1.translateX = -foot_pivot.rotateZ;
vector1.translateZ = foot_pivot.rotateX;
// Normalize the vector
vector $norm = unit(<<vector1.translateX,vector1.translateY,vector1.translateZ>>);
// Use the normalized coordinates to set the position of norm_vector
normalized_vector1.translateX = $norm.x * $radius;
normalized_vector1.translateZ = $norm.z * $radius;
// Animate the pivot_rotator pivot point to match the normalized vector
foot_pivot.rotatePivotX = $norm.x * $radius;
foot_pivot.rotatePivotZ = $norm.z * $radius;
</pre>
<p><em>(This step is optional or could be done differently.)</em> - Another thing I like to do is connect the “foot_roll” translation to the “foot_pivot.rotatePivotTranslate”. Then you can translate the “foot_roll” to create sliding effects in parent space. So even though the foot roll will be rotated, moving forward in Z will slide the foot along the ground all with one control object.</p>
<blockquote>
<p>**Update: <a href="http://www.robotsquids.blogspot.ca/2013/09/sliding-pivot-foot-roll-tutorial.html">Armin Halac of Robot Squids has created a video tutorial</a> showing how you can build a set up like this that lets use you an arbitrary foot shape using only Maya nodes. Make sure to <a href="http://www.robotsquids.blogspot.ca/2013/09/sliding-pivot-foot-roll-tutorial.html" title="Maya foot roll tutorial">check out his foot roll tutorial here</a>.</p>
</blockquote>
<p><strong> Here is a scene file you can download (Maya 2012)</strong></p>
<p>If you’d like to see the finished expression in action. The expression is included as a text file. <a href="http://chrislesage.com/wp-content/uploads/2012/03/cylinder_roll_example_scene.zip"><strong>Download the finished, animated scene.</strong></a> Let me know in the comments if you found this helpful or if I can explain anything more clearly. Thanks for reading.</p>
<hr>
<h2>Comments (closed)</h2>
<p><strong><a href="#28" title="2012-04-03 07:15:45">Ehsan <span class="caps">HM</span></a>:</strong> Very creative Chris, Thanks for sharing!</p>
<p><strong><a href="#78" title="2013-09-19 16:35:35">Chris Lesage</a>:</strong> Update: Armin Halac of Robot Squids has created a great video tutorial showing how you can set this up using Maya nodes, and with any arbitary foot shape: http://www.robotsquids.blogspot.ca/2013/09/sliding-pivot-foot-roll-tutorial.html</p>Use K to Easily Navigate Your Maya Timeline2012-03-07T15:17:00-05:002012-03-07T15:17:00-05:00Chris Lesagetag:chrislesage.com,2012-03-07:/tip-of-the-day/use-k-to-easily-navigate-your-maya-timeline/<p>There are tons of features and hotkeys and hidden marking menus in Maya that are extremely useful but surprisingly seldom known. While everyone is talking about big new features, these underdogs can easily be forgotten.</p>
<p>I just started a <em>“tip of the day”</em> with my animators at work because I realized that there are lot of these things that they aren’t aware of, but being a major geek, I’ve read through the help docs like a crime-thriller novel …</p><p>There are tons of features and hotkeys and hidden marking menus in Maya that are extremely useful but surprisingly seldom known. While everyone is talking about big new features, these underdogs can easily be forgotten.</p>
<p>I just started a <em>“tip of the day”</em> with my animators at work because I realized that there are lot of these things that they aren’t aware of, but being a major geek, I’ve read through the help docs like a crime-thriller novel. (It turns out the Zoom Tool did it.) Today’s was such a hit that I thought I’d start posting some of the best ones here.</p>
<h3>Tip of the day</h3>
<p>Hold down ‘K’ and drag in the viewport. Your timeline will scrub as if you were dragging down on the time slider. Middle-mouse drag and your characters will stay in place for copying keyframes. (Again, same as the time slider.) This also works in the graph editor and the dope sheet.</p>
<h3>Customize the Hotkey</h3>
<p>In the hotkey editor this feature can be found under Tools > TimeDraggerToolActivate. This means that you can map it to another key if you wish. You could also invoke the context in your own custom <span class="caps">UI</span> tools.</p>Mini Mammoth Part 3: Modelling and Topology in 3D-Coat2012-03-05T16:28:00-05:002012-03-05T16:28:00-05:00Chris Lesagetag:chrislesage.com,2012-03-05:/character-rigging/mini-mammoth-part-3-modelling-and-topology-in-3d-coat/<p><img alt="mini mammoth final wireframe render" src="http://chrislesage.com/wp-content/uploads/2012/03/mini-mammoth-final-wireframe-render.jpg"></p>
<p><strong>Here is Part 3 of rigging Mini Mammoth</strong>. I’ve now got a finished model. This turned into a huge step, because I was learning a ton about modelling and topology in 3D-Coat, which turned into a 2-week long adventure of tutorials and manuals. I made a lot of mistakes as well which I’ll talk a little bit about. All in the spirit of learning!</p>
<p><strong>This is the last post before I get into the actual character rigging.</strong></p>
<p>First …</p><p><img alt="mini mammoth final wireframe render" src="http://chrislesage.com/wp-content/uploads/2012/03/mini-mammoth-final-wireframe-render.jpg"></p>
<p><strong>Here is Part 3 of rigging Mini Mammoth</strong>. I’ve now got a finished model. This turned into a huge step, because I was learning a ton about modelling and topology in 3D-Coat, which turned into a 2-week long adventure of tutorials and manuals. I made a lot of mistakes as well which I’ll talk a little bit about. All in the spirit of learning!</p>
<p><strong>This is the last post before I get into the actual character rigging.</strong></p>
<p>First, I decided that I liked how the prototype model looked, so instead of starting from scratch, I began editing it. I started by carving out a mouth cavity and lowering the eyes.</p>
<p><img alt="mini mammoth mouth modelling" src="http://chrislesage.com/wp-content/uploads/2012/03/mini-mammoth-mouth-modelling.jpg"></p>
<p><img alt="mini mammoth WIP 1" src="http://chrislesage.com/wp-content/uploads/2012/03/mini-mammoth-wip-01.jpg"></p>
<p><img alt="mini mammoth WIP 2" src="http://chrislesage.com/wp-content/uploads/2012/03/mini-mammoth-wip-02.jpg"></p>
<p>The funny thing about this entire process was that after I finished tediously making a change, I found a feature in 3D-Coat that makes it fast and easy!</p>
<p>For example, to change the eye, I filled in the eye sockets, transformed the eye geometry down, and then using the Sphere tool, gouged a new hole for the eye sockets.. After that, I learned that you can create a low-resolution cache, make changes and then propagate those changes back to the high-resolution voxels. This lets you make big changes to the structure of your model without destroying the finer details. (Otherwise, if you just move things around, you’ll tend to get a mushy mess.) I could have done this and used the move tool to lower the eyes very quickly.</p>
<p>In fact, using the low-proxy cache is a good workflow for modelling non-linearly, because even after you have details, you can change proportions and posing. I’ve started doing this now, and it has loosened me up a lot. It is also far faster to edit, because it is lower resolution.</p>
<p>Another example, after I took all these screenshots with different angles, I found out that you can save camera angles. That would have been better for the comparison shots in the topology stages below. It would also be good for making animated gifs of time-lapse progress.</p>
<p>Next, I made a few changes to the nose and ears to make the edges look a bit more hard and defined. I also removed the tail and the eyebrows. (I’ll add those separately later.)</p>
<p><img alt="mini mammoth WIP 3" src="http://chrislesage.com/wp-content/uploads/2012/03/mini-mammoth-wip-03.jpg"></p>
<h3>Mesh Retopology</h3>
<p>I decided to call it done and moved on to the Retopo tool for creating my polygon topology. This was an exciting stage, because I wasn’t aware until a few months ago that tools like these existed. Modelling used to be a relatively tedious process, and now it feels very artistic in comparison. (I would also like to try ZBrush someday.)</p>
<p>The concept here is that you have your voxel model underneath, and you are adding polygons on top to the surface. So you can use the auto-tools or just draw polygons manually.</p>
<p>I did a few experiments and followed a couple of tutorials, but I was new to this. The best part about this tool is that it is iterative. You create a few “suggestion strokes” and then run the tool and see what you get as a result. If it is very messy, you just delete the polygons and run it again. (Or keep the polygons and stitch them together from various layers.)</p>
<p>Different patterns of suggestion strokes results in different mesh topology. Orange lines are closed loops, and green lines are directional indicators. The dark area indicates where you want more density. Eventually, I rested on the 3rd iteration below: </p>
<p><img alt="mini mammoth edgeloops 1" src="http://chrislesage.com/wp-content/uploads/2012/03/mini-mammoth-edgeloops-01.jpg">
<img alt="mini mammoth edgeloops result 1" src="http://chrislesage.com/wp-content/uploads/2012/03/mini-mammoth-edgeloops-result-01.jpg"></p>
<p><img alt="mini mammoth edgeloops 2" src="http://chrislesage.com/wp-content/uploads/2012/03/mini-mammoth-edgeloops-02.jpg">
<img alt="mini mammoth edgeloops result 2" src="http://chrislesage.com/wp-content/uploads/2012/03/mini-mammoth-edgeloops-result-02.jpg"></p>
<p><img alt="mini mammoth edgeloops 3" src="http://chrislesage.com/wp-content/uploads/2012/03/mini-mammoth-edgeloop-03.jpg">
<img alt="mini mammoth edgeloops result 3" src="http://chrislesage.com/wp-content/uploads/2012/03/mini-mammoth-edgeloops-result-03.jpg"></p>
<p>Now at first glance that might look pretty clean, but there are several 5-sided polys, triangles and a whole bunch of spiral edge-rings. The legs were especially problematic. So with the results as a starting point, there is some clean-up to do.</p>
<p>This is the stage where I wasted the most time!</p>
<p>At this point I wasn’t sure how many polys to use. In hindsight it turns out I was using too many, because it is very easy to sub-divide later. It made editing more cumbersome. I was sliding edges around one-by-one, deleting and merging polys and then hitting “Relax” to smooth out the results. When you hit “Relax”, sometimes things you don’t want to move will shift around and warp. So slowly, my edge-rings around the legs were drifting and getting crooked.</p>
<p>After a long tedious session of these types of edits (which by the way were a <span class="caps">JOY</span> compared to the old way I used to model years ago.) I found two powerful features that I had missed:</p>
<p>1. The “Brush” tool. How did I miss this!? It is brilliant. Using the brush tool, you can slide regions of vertices around. The beauty of it is that it stays adhered to the voxel surface below, so you can really get loose and messy. Hold down shift (as with most tools in 3D-Coat) and you can relax and smooth the vertices, again while sticking to the surface. This solved my drifting problem with the Relax tool and made the whole process 40X easier! (give or take a few X’s.)</p>
<p>2. You can delete polygons and use the Strokes tool manually. I thought the Strokes tool was only part of the Auto-Retopo tools. With that in mind, I deleted and rebuilt the eye region, to get a better round edge-loop structure on the face.</p>
<p><img alt="mini mammoth WIP 4" src="http://chrislesage.com/wp-content/uploads/2012/03/mini-mammoth-wip-04.jpg"></p>
<p>So yadda yadda yadda… I kept doing these edits, especially around the mouth and legs and now I have a finished body model with 6892 faces. There is still a weird portion on the inside of the leg where the polys are running a bit diagonally and might cause artifacting, but I am going to test in Maya before I bother spending too much time to fix it. We might never see it. All in all, I’m happy with everything I learned and I know I could model more characters even faster. </p>
<h3>The Result:</h3>
<p><img alt="mini mammoth final 1" src="http://chrislesage.com/wp-content/uploads/2012/03/mini-mammoth-final-01.jpg">
<img alt="mini mammoth final 2" src="http://chrislesage.com/wp-content/uploads/2012/03/mini-mammoth-final-02.jpg">
<img alt="mini mammoth final 3" src="http://chrislesage.com/wp-content/uploads/2012/03/mini-mammoth-final-03.jpg">
<img alt="mini mammoth final 4" src="http://chrislesage.com/wp-content/uploads/2012/03/mini-mammoth-final-04.jpg">
<img alt="mini mammoth final 5" src="http://chrislesage.com/wp-content/uploads/2012/03/mini-mammoth-final-05.jpg"></p>
<h3>Next Step: Export to Maya for Rigging</h3>
<p>With a nice clean mesh, I think it will be possible to create some great squash-and-stretch cartoony effects. I’ll save the <span class="caps">UV</span> unwrapping for later. (This is another easy tool in 3D-Coat.) The next step is to begin doing some rig tests and prototyping. There is a chance I’ll have to make some changes.</p>
<ul>
<li>Will the geometry deform properly? (quick skinning tests)</li>
<li>Should the trunk have been modelled straight? (I might still have to fix this.)</li>
<li>Prototype a cylindrical auto foot-roll, which can roll in any direction.</li>
<li>Model small details like tongue, tail, teeth and eyebrows. (and possibly some tufts of fur and other details.)</li>
<li>Create some nicer, asymmetrical tusks.</li>
</ul>Python: String Formatting and Enumerate2012-02-21T18:00:00-05:002012-02-21T18:00:00-05:00Chris Lesagetag:chrislesage.com,2012-02-21:/python/python-string-formatting-and-enumerate/<p>As a mostly self-taught Python scripter, I try to keep on top of best-practices and constantly learn, because I realize how easily bad habits can slip in. I’ve recently learned these <a href="http://www.robg3d.com/?p=933" title="doubly-mutable antipatterns">bad habits</a> are known as <a href="http://blog.sanctum.geek.nz/vim-anti-patterns/" title="vim-anti-patterns">anti-patterns</a>.</p>
<p>That said, I learned a couple new Python tricks this week.</p>
<h3>1. Better String Formatting Using Format()</h3>
<p>If you’ve used string formatting before, this is very similar, except the replacement fields are inside {} brackets, and you can use variables as keywords …</p><p>As a mostly self-taught Python scripter, I try to keep on top of best-practices and constantly learn, because I realize how easily bad habits can slip in. I’ve recently learned these <a href="http://www.robg3d.com/?p=933" title="doubly-mutable antipatterns">bad habits</a> are known as <a href="http://blog.sanctum.geek.nz/vim-anti-patterns/" title="vim-anti-patterns">anti-patterns</a>.</p>
<p>That said, I learned a couple new Python tricks this week.</p>
<h3>1. Better String Formatting Using Format()</h3>
<p>If you’ve used string formatting before, this is very similar, except the replacement fields are inside {} brackets, and you can use variables as keywords or an index.</p>
<p>examples:</p>
<div class="highlight"><pre><span></span><span class="k">print</span> <span class="s1">'We are the {0} who say "{1}!"'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="s1">'knights'</span><span class="p">,</span> <span class="s1">'Ni'</span><span class="p">)</span>
<span class="k">print</span> <span class="s1">'We are the {1} who say "{0}!"'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="s1">'Ni'</span><span class="p">,</span> <span class="s1">'knights'</span><span class="p">)</span>
<span class="k">print</span> <span class="s1">'We are the {people} who say "{quote}!"'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">people</span><span class="o">=</span><span class="s1">'knights'</span><span class="p">,</span> <span class="n">quote</span><span class="o">=</span><span class="s1">'Ni'</span><span class="p">)</span>
</pre></div>
<p>There are also lots of examples of how to format numbers or create precise column spacing. The ” <em>old string formatting</em>” is eventually going to be removed from Python. There is likely no rush to switch, but it is less flexible and a bit harder to read:</p>
<div class="highlight"><pre><span></span><span class="k">print</span> <span class="s1">'We are the </span><span class="si">%s</span><span class="s1"> who say </span><span class="si">%s</span><span class="s1">!'</span> <span class="o">%</span> <span class="p">(</span><span class="s1">'knights'</span><span class="p">,</span> <span class="s1">'Ni'</span><span class="p">)</span>
</pre></div>
<p>source: <a href="http://docs.python.org/tutorial/inputoutput.html">http://docs.python.org/tutorial/inputoutput.html</a></p>
<h3>2. Looping With Enumerate()</h3>
<p>One of the common things you want when looping through things is an index counter. You can do this a few various ways: counter += 1 for i in range(): or you can use each.index() on array items. There is a better way:</p>
<p><a href="http://www.python.org/dev/peps/pep-0279/" title="Python enumerate">Enumerate() is nice <span class="caps">PEP</span>-friendly way</a> to get a “a compact, readable, reliable index notation” in loops. It works even when you don’t have an array to count, or a known length (for doing a range()). You use two variables in your for loop, and the first is your index. It is much nicer than having a separate counter or measuring the length of something which may change inside the loop.</p>
<p><em>(This is a PyMEL example in Maya and assumes you have a selection of objects.)</em></p>
<div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">pymel.core</span> <span class="kn">as</span> <span class="nn">pm</span>
<span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">each</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">pm</span><span class="o">.</span><span class="n">selected</span><span class="p">()):</span>
<span class="k">print</span> <span class="n">i</span><span class="p">,</span> <span class="n">each</span>
<span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">each</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">([</span><span class="s1">'some'</span><span class="p">,</span> <span class="s1">'array'</span><span class="p">,</span> <span class="s1">'here'</span><span class="p">]):</span>
<span class="k">print</span> <span class="n">i</span><span class="p">,</span> <span class="n">each</span>
</pre></div>
<h3>3. Put Them Together</h3>
<p>Let’s do a simple example where we also use .format() to rename a series of objects. I’ll use {1:02d} to automatically add frame-padding. {1:__} is the replacement field index. {__:02d} is the frame-padding. (You can also convert to percentages, hexadecimal, dates, change the column spacing, etc. etc. This is just one small example.)</p>
<div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">each</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">pm</span><span class="o">.</span><span class="n">selected</span><span class="p">()):</span>
<span class="n">newName</span> <span class="o">=</span> <span class="s1">'{0}_{1:02d}'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="s1">'right_whisker'</span><span class="p">,</span> <span class="n">i</span><span class="p">)</span>
<span class="n">pm</span><span class="o">.</span><span class="n">rename</span><span class="p">(</span><span class="n">each</span><span class="p">,</span> <span class="n">newName</span><span class="p">)</span>
</pre></div>
<p>The nice thing about .format() is how easy it is to read and edit, since the replacement fields are clearly separated by brackets and you can pass any variables to them. Again this isn’t new, but it is easier to read than the old string formatting. So let’s play with this a bit and expand the example to automatically rename the object as “left” or “right”, depending on its translation in X.</p>
<div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">each</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">pm</span><span class="o">.</span><span class="n">selected</span><span class="p">()):</span>
<span class="k">if</span> <span class="n">each</span><span class="o">.</span><span class="n">tx</span><span class="o">.</span><span class="n">get</span><span class="p">()</span> <span class="o">&</span><span class="n">gt</span><span class="p">;</span> <span class="mi">0</span><span class="p">:</span>
<span class="n">side</span> <span class="o">=</span> <span class="s1">'left'</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">side</span> <span class="o">=</span> <span class="s1">'right'</span>
<span class="n">newName</span> <span class="o">=</span> <span class="s1">'{0}_{1}_{2:02d}'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">side</span><span class="p">,</span> <span class="s1">'whisker'</span><span class="p">,</span> <span class="n">i</span><span class="p">)</span>
<span class="n">pm</span><span class="o">.</span><span class="n">rename</span><span class="p">(</span><span class="n">each</span><span class="p">,</span> <span class="n">newName</span><span class="p">)</span>
</pre></div>
<p>In the past, one of the most common ways I’ve created an index count is by measuring a length of a list or array or by using .index() to return the index of an array item. In comparison, this looks very ugly now. Plus, if you were to delete some objects inside the loop, the length of your range might change.</p>
<div class="highlight"><pre><span></span><span class="n">objects</span> <span class="o">=</span> <span class="n">pm</span><span class="o">.</span><span class="n">selected</span><span class="p">()</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="nb">len</span><span class="p">(</span><span class="n">objects</span><span class="p">)):</span>
<span class="k">print</span> <span class="n">i</span><span class="p">,</span> <span class="n">objects</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
</pre></div>
<p>Two useful new tools for the arsenal. If you have any tips, suggestions or improvements, leave a comment. Next up, I’ll be getting back to the Mini Mammoth rigging after a bit of a hiatus.</p>
<hr>
<h2>Comments (closed)</h2>
<p><strong><a href="#23" title="2012-02-22 00:05:36">Alexander Morano</a>:</strong> How does this work with the log_formatter strings? E.G.: _log_format = ‘%(asctime)-9s %(levelname)-7s %(name)-40s %(message)s’ since that is a template, are the formatters for the logger class updated in 2.6-> ? Cheers.</p>
<p><strong><a href="#24" title="2012-02-22 01:59:52">Chris</a>:</strong> @Keir: Ah thanks. Yes it seems it very similar. I suppose the only advantage is the readability. @Alexander: That’s a good question, but I’m not sure since I use pymel’s plogging module. There doesn’t seem to be any word on format() in regards to log formatting does there?</p>
<p><strong><a href="#22" title="2012-02-21 22:23:16">Keir</a>:</strong> The % based string substitution also has a couple of cool tricks. [code] print ‘We are the %s who say “%s!”’ % (‘knights’, ‘Ni’) print ‘We are the %(people)s who say “%(quote)!”’ % {people:’knights’, quote:’Ni’} [\code] [code] people = ‘knights’ quote = ‘Ni’ print ‘We are the %(people)s who say “%(quote)!”’ % locals() [\code]</p>
<p><strong><a href="#25" title="2012-02-25 09:43:38">Rob Galanakis</a>:</strong> Good post but two problems: First is the for/if/else antipattern. You have a known case (each.tx.get() == 0), why are you testing? Pull the loop code into an inner function, call it for the explicit case, then call it for the loop case. Not only does for/if/else not perform well, it is difficult to read because it introduces an extra branch for every loop iteration, even though you should only have to think about the ‘0 case’ logic once. Second is mutating a collection as you loop over it. Not only is this actually illegal with many structures (python dicts) and languages (like C#), it is a great way to write code that is incredibly difficult to understand, especially if, say, your collection is pymel nodes. There is never ever a reason to mutate within a loop. Assign things ‘transactionally’ instead- that’s a really loose usage of the word transaction, but I mean, just build up new structures and assign them to what you need to assign them to when done.</p>
<p><strong><a href="#26" title="2012-02-25 15:05:48">Chris</a>:</strong> Awesome Rob, thanks for the great feedback. That makes total sense. I always find your blog and <span class="caps">TAO</span> posts very valuable to read and re-read. 2 years into Python I consider myself a beginner and you very often introduce concepts, rules and guidelines to which I was completely unaware. (Actually my real autorig code does explicitly call functions. This was just a quick contrived example.)</p>
<p><strong><a href="#298" title="2016-03-07 15:08:52">gr</a>:</strong> for i, item in enumerate(L): # … compute some result based on item … L[i] = result</p>Using Proxy Geometry For Better Skinning Results2012-02-10T16:07:00-05:002012-02-10T16:07:00-05:00Chris Lesagetag:chrislesage.com,2012-02-10:/character-rigging/using-proxy-geometry-for-better-skinning-results/<p>Here is a simple skinning trick I like to use, which comes in handy for a lot of different rigging situations.</p>
<p>In the images below, I was rigging a wolf’s tongue with spline <span class="caps">IK</span> that needed to be very flexible. (If you count, you’ll notice that there are 12 controllers. 4 main controllers and 8 extra offset controllers to bend and twist the tongue into a variety of shapes.) The skinning was proving to be tedious, because the …</p><p>Here is a simple skinning trick I like to use, which comes in handy for a lot of different rigging situations.</p>
<p>In the images below, I was rigging a wolf’s tongue with spline <span class="caps">IK</span> that needed to be very flexible. (If you count, you’ll notice that there are 12 controllers. 4 main controllers and 8 extra offset controllers to bend and twist the tongue into a variety of shapes.) The skinning was proving to be tedious, because the geometry kept collapsing and self-colliding. So here is what I did:</p>
<p><strong>The Scenario</strong>: You have some tongue geometry (or other semi-flat geometry) which needs to be very flexible but the rig has a lot of bones and painting accurate weights is tedious and error-prone!</p>
<p><img src="http://chrislesage.com/wp-content/uploads/2012/02/wolf_tongue_colliding.jpg" alt="wolf tongue colliding" title="wolf_tongue_colliding" width="360" height="312" class="size-full wp-image-185" /></p>
<blockquote>
<p>Look at that unsightly and embarrassing interpenetration!</p>
</blockquote>
<p><strong>Solution</strong>: Use a poly plane or other simplified geometry as a proxy. Fit it inside the geometry, and skin that instead. When you are done painting, use Copy Skin Weights to copy the weights from the proxy geometry to the full geometry.</p>
<p>The settings I use for Copy Skin Weights are:</p>
<ul>
<li>Surface Association: <strong>Closest point on surface</strong></li>
<li>Influence Association 1: <strong>Closest Joint</strong></li>
<li>Influence Association 2: <strong>Closest Bone</strong></li>
<li>Influence Association 3: <strong>Name</strong> (This 3rd entry is usually optional and makes no difference. When copying from the same geometry, like a body to a body, use “One to One” instead.)</li>
<li>Normalize: <strong>Not checked</strong></li>
</ul>
<p><img src="http://chrislesage.com/wp-content/uploads/2012/02/skinning_a_tongue_using_poly_plane.jpg" alt="skinning a tongue using a polygon plane" title="skinning_a_tongue_using_poly_plane" width="368" height="364" class="size-full wp-image-181" /></p>
<blockquote>
<p>Using a proxy object to skin the 3D geometry</p>
</blockquote>
<p><img src="http://chrislesage.com/wp-content/uploads/2012/02/flexible_tongue_rig.jpg" alt="flexible tongue rig" title="flexible_tongue_rig" width="318" height="395" class="size-full wp-image-180" /></p>
<blockquote>
<p>The final result is fast and flexible</p>
</blockquote>
<p>This makes it very easy for both sides of the tongue to have the same weighting, without tedious painting, which means it will twist and bend a lot further without self-colliding. When your geometry has a lot of folds and wrinkles it is also a lot easier to get your brush along the flat, uniform geometry of a plane. This technique also works in any 3D package which supports copying weights from one object to another. In <span class="caps">XSI</span> you can do the exact same thing using <span class="caps">GATOR</span>.</p>
<p>I have also used this technique to copy weights from a stretched sphere to weight complex hair geometry. You could also use it to copy weights from low-res geometry to high-res geometry. You will likely have to do a bit of cleaning up afterwards, but it could be a good way to get 90% of your weight painting done very quickly.</p>
<p>When you are done, you can simply delete the geometry, or tuck it away in a hidden group for later editing. My next goal with this is to figure out a way to copy weights locally on complex geometry. For example, if the tongue is attached to the body, how would you grab just the tongue weights?</p>
<hr>
<h2>Comments (closed)</h2>
<p><strong><a href="#21" title="2012-02-14 16:14:58">Chris</a>:</strong> Ah cool! I didn’t realize that. It works very well! If you needed to select very complex geometry or wanted to paint selection, I suppose you could create a script that would store your vertex selections, one object at a time, and then re-select them when you are ready to copy the weights. Thanks for the tip Ehsan!</p>
<p><strong><a href="#19" title="2012-02-13 14:05:21">Matt Murray</a>:</strong> Sweet! Thanks for the tip :D</p>
<p><strong><a href="#20" title="2012-02-14 08:12:22">Ehsan <span class="caps">HM</span></a>:</strong> Hi, Thanks for sharing dude. To copy weights locally on complex geometry, you could use the same technique but you should select the vertices of the destination geo. Selecting is a bit tricky though but you can select both geometries first and isolate them. select you proxy geo then hide it’s display layer and shift select vertices of the destination geo. You might find an easier solution but this is what I came with so far and it works. :) Cheers.</p>
<p><strong><a href="#27" title="2012-03-09 16:35:40">Chris</a>:</strong> Another useful application: You can’t (as far as I can tell) paint weights or smooth skin weights on a lattice. But you can definitely copy weights from geometry to a lattice!</p>
<p><strong><a href="#40" title="2012-12-19 18:51:41">like</a>:</strong> Hi there! I could have sworn I’ve been to this site before but after looking at some of the articles I realized it’s new to me. Nonetheless, I’m definitely delighted I came across it and I’ll be book-marking it and checking back often!</p>
<p><strong><a href="#85" title="2013-10-06 21:06:05">Armin Halac</a>:</strong> Hi Chris, very useful technique. Just saved me a ton of work on skinning an elephants ear. Cheers!</p>Mini Mammoth Part 2: Sketching & 3D Sculpting2012-01-23T18:10:00-05:002012-01-23T18:10:00-05:00Chris Lesagetag:chrislesage.com,2012-01-23:/character-rigging/mini-mammoth-part-2-sketching-3d-sculpting/<p><img alt="mini mammoth walking" src="http://chrislesage.com/wp-content/uploads/2012/01/mini-mammoth-walking.jpg"></p>
<p>So now we are on to <strong>part 2 of the Making Of Mini Mammoth</strong> where I am documenting the entire process of designing a cartoony character rig. In this step, I am doing a bunch of sketching from photo references and sculpting a quick prototype 3D model to get even more ideas. We’re almost ready to start the actual modelling, but first…</p>
<h3><strong>Sketching Solves Problems</strong></h3>
<p>Design-based drawing is ultimately about solving problems, so quality isn’t at all important …</p><p><img alt="mini mammoth walking" src="http://chrislesage.com/wp-content/uploads/2012/01/mini-mammoth-walking.jpg"></p>
<p>So now we are on to <strong>part 2 of the Making Of Mini Mammoth</strong> where I am documenting the entire process of designing a cartoony character rig. In this step, I am doing a bunch of sketching from photo references and sculpting a quick prototype 3D model to get even more ideas. We’re almost ready to start the actual modelling, but first…</p>
<h3><strong>Sketching Solves Problems</strong></h3>
<p>Design-based drawing is ultimately about solving problems, so quality isn’t at all important compared to just looking and observing the world.</p>
<p><img alt="Design sketches for Mini Mammoth" src="http://chrislesage.com/wp-content/uploads/2012/01/mini-mammoth-sketchsheet-001.jpg"></p>
<blockquote>
<p>Design sketches for Mini Mammoth</p>
</blockquote>
<p>I’m not the best draftsman, and they are definitely not going to dedicate an Art-Of book to me just yet, but it is a very important step to visually work out all the things we’ll have to pay attention to when we get to the character rigging stage. Drawing is also very important <strong>because it is fast</strong>. You can collect a lot of ideas in a short period of time and end up surprising yourself with ideas you would not have thought of if you had been tempted to jump straight into modelling.</p>
<p>Even when I am coding Python tools, I often find it very helpful to draw out my ideas first. I constantly keep a notebook full of notes and doodles beside me.</p>
<p>At this point, I’m just trying to get lots of ideas for shapes, style and proportions. This is one of the most fun steps because anything goes. I even spent some time drawing bears.</p>
<p><img alt="Some more design sketches for Mini Mammoth" src="http://chrislesage.com/wp-content/uploads/2012/01/mini-mammoth-sketchsheet-002.jpg"></p>
<blockquote>
<p>Some more design sketches for Mini Mammoth</p>
</blockquote>
<p><strong>Design Considerations So Far:</strong></p>
<ul>
<li>The mammoth’s trunk is mostly drawn in an interesting S shape, but I want it to be completely flexible and stretchy, including doing a water-passing-through-a-hose effect. So ultimately, I’ll likely model it in a straight line. When making a rig, <strong>it is usually easier to bend straight geometry than it is to straighten bent geometry</strong>. This is true when modelling any body part that will need to bend a lot, like a trunk, tongue or tail.</li>
<li>In some of the drawings I noticed that the tusks will overlap with the mouth, and it will be an important part of how the mouth looks. The trunk and tusks will <em>essentially be the upper lips</em>.</li>
<li>I’ve learned that there are a wide variety of mammoth and elephant ears. I’ll need to decide how floppy and how big they will be.</li>
<li>The long tusks of a mammoth make a really beautiful curve. This will be an important part to get right.</li>
<li>I am imagining giving him a thick coat of fur. How will I do it? There a few ways I could do it. Geometry, Maya hair, separate pieces of geometry? A lot to think about.</li>
<li>Did you know that <a href="http://www.youtube.com/watch?v=PKWRCW7PYKw">elephants have a 3rd eyelid membrane that slides sideways as they blink</a>?</li>
</ul>
<h3>Building a Prototype Model in 3D-Coat</h3>
<p>My original sketch wasn’t very detailed, and I wasn’t sure if the shapes I was drawing were even possible in 3D! So I started to model a prototype in <a href="http://3d-coat.com/">3D-Coat</a>.</p>
<p><img alt="3D turntable of Mini Mammoth" src="http://chrislesage.com/wp-content/uploads/2012/01/mini-mammoth-turntable.gif"></p>
<blockquote>
<p>A digital sculpt in 3D-Coat</p>
</blockquote>
<p>I really like how it turned out! At this point, I am just playing with shapes in 3D. <em>This is not a final model</em>. A lot of details like the ears will still change a lot so I am not too worried about following the design so far. Its just a 3D doodle.</p>
<p>Digital voxel sculpting in 3D-Coat is a lot of fun! You are very free to push and pull your model and experiment. It feels as loose as drawing, the tools are very intuitive. You can even build an armature (The ‘Curves’ tool) or drop shapes in (The ‘Primitives’ tool) using spheres, squares and cylinders to build up a model very quickly.</p>
<p><img alt="3d-coat armature" src="http://chrislesage.com/wp-content/uploads/2012/01/3d-coat-armature.jpg"></p>
<blockquote>
<p>Building an armature in 3D-Coat</p>
</blockquote>
<p>Immediately, I began to see some interesting patterns emerge:</p>
<ul>
<li>The legs are almost perfect cylinders. I like this a lot. They will bend and stretch, but their default shape will be very simple.</li>
<li>The trunk makes some really cool undulating waves all the way up to the top of the head.</li>
<li>The eyebrows need more design work so they don’t look like Groucho Marx. (Though that could be fun too!) Right now he looks angry in a lot of the drawings, but he’ll have a wider range of expressions when I design the facial rigging.</li>
<li>I like how the foundation of Mini Mammoth is a simple egg shape. But I also started getting some interesting square shapes in the hindquarters. I will hint at real anatomy in the pelvis.</li>
</ul>
<h2>The Lessons</h2>
<h4>#1. Always use references.</h4>
<p>I started out drawing a lot of sketches from my imagination, but the ones I sketched while looking at references of other animals were the ones that solved the most problems and made the design more clear in my mind.</p>
<p>As I said earlier; drawing for design is a problem-solving process. At this point, it is not about creating art. The more I drew from references, the more I realized things that I would have to think about during the modelling and rigging stages.</p>
<h4>#2. Don’t Limit Your Inspiration</h4>
<p>I was looking at one of my drawings and it reminded me of a bear walking. So I studied a few pictures of bears. A bear has a big, lumbering walk with shorter legs than an elephant (just like Mini Mammoth.) So when I go to create a walk cycle, I’ll be largely inspired by bears. Mini Mammoth might look very small but he is going to walk with a big, heavy, camera-shaking gait!</p>
<p><img alt="bear walking reference" src="http://chrislesage.com/wp-content/uploads/2012/01/bear-walking-reference1.jpg"></p>
<p><img alt="mini mammoth 3d prototype" src="http://chrislesage.com/wp-content/uploads/2012/01/mini-mammoth-3d-prototype.jpg"></p>
<p><strong>Coming Up Next:</strong></p>
<p>I’ll finalize the design, make a couple of polished drawings, and then go back to 3D-Coat to start the actual modelling. After that, I’ll go through the auto re-topology of the model (an amazing feature of 3D-Coat which generates the polygon edge-loops) and create the texture <span class="caps">UV</span>’s for preparing the model to export into Maya. </p>
<p>Until then!</p>
<h2>Comments (closed)</h2>
<p><strong><a href="#18" title="2012-01-27 17:15:45">Chris</a>:</strong> Thanks Lisa. Nice to hear from you. I look forward to getting into the actual rigging and bringing this guy to life.</p>
<p><strong><a href="#17" title="2012-01-27 17:04:22">Lisa Doucet</a>:</strong> Chris, I loved reading your lesson. I find it <span class="caps">VERY</span> interesting how you manage to break it down into bite-size morsels. I look forward to reading more !</p>Mini Mammoth Part 1: The Making Of A Cartoon Character Rig2012-01-17T03:50:00-05:002012-01-17T03:50:00-05:00Chris Lesagetag:chrislesage.com,2012-01-17:/character-rigging/mini-mammoth-part-1-the-making-of-a-cartoon-character-rig/<p><strong>Hi everyone. This is the first post in a series where I take this simple doodle of a cartoon mammoth:</strong></p>
<p><img alt="mini mammoth first sketch" src="http://chrislesage.com/wp-content/uploads/2012/01/mini-mammoth-first-sketch.jpg"></p>
<p><strong>…and turn him into a fully animated, super-flexible cartoony character rig in Maya!</strong></p>
<p>I’ll be documenting the entire process from design and modelling to the creation of the entire rig. It won’t be a step-by-step tutorial, but it will show my entire thought process as I rig, mistakes and all. It might get messy, but I know I …</p><p><strong>Hi everyone. This is the first post in a series where I take this simple doodle of a cartoon mammoth:</strong></p>
<p><img alt="mini mammoth first sketch" src="http://chrislesage.com/wp-content/uploads/2012/01/mini-mammoth-first-sketch.jpg"></p>
<p><strong>…and turn him into a fully animated, super-flexible cartoony character rig in Maya!</strong></p>
<p>I’ll be documenting the entire process from design and modelling to the creation of the entire rig. It won’t be a step-by-step tutorial, but it will show my entire thought process as I rig, mistakes and all. It might get messy, but I know I’ll learn a lot and hopefully you will too.</p>
<p>This isn’t the full “design”. That will come a bit later. Right now it is just a quick 3-inch doodle that I sketched while at work. I am choosing this funny little character for a few reasons, because it will be especially challenging in a few ways: </p>
<h4>The Challenge</h4>
<p>1. The challenge of small cartoony rigs is that there is lots of overlapping influence between the different body parts. Take a look at this image.</p>
<p><img alt="mini mammoth design considerations" src="http://chrislesage.com/wp-content/uploads/2012/01/mini-mammoth-design-considerations.jpg"></p>
<p>For example, the cavity of the mouth and the shape of the lips is going to overlap all the way down to his knees. So when he opens his mouth his legs are going to move! His head is so big in relation to his body that he is basically a walking face. When rigging a normal-sized human or creature, all the body parts are distinct and separate and it is easier to paint the influence. So I am going to have to very carefully consider how I do everything from the facial rig to the way the limbs bend the body.</p>
<p>2. I am going to design him so that he has a lot of exaggerated squash and stretch. His trunk will stretch, bulge and grab on to things. How will such a short little trunk grab things? We will see!</p>
<p>3. It will just be a lot of fun figuring out how to make this guy move in an appealing and believable way! </p>
<h4>The End Result?</h4>
<p>The end result will be an animated short, featuring “Mini Mammoth”. I am not sure yet if I am going to texture and render it, but we will see! Stay tuned!</p>