Posted on Jul 10, 2010

Auto Image Size Reduction Using PHP

Bravo! Bravo! I knew I can do it. Stayed up late last night, learning PHP code. Haha! I'm no George Malley (from Phenomenon, John Travolta), who devoured an English-Spanish dictionary on a 20 minute drive to a sick lady they all thought was possessed (stomach flu can be the devil), but last night, I set out to accomplish something and today I woke up to find out that it actually worked.I am very much in love with my plain and simple theme. But what readers do not see is underneath this smooth exterior, there's a violent monster ruthlessly cleaning up content, a.k.a. wordpress's plugin system. To give you a brief picture, let me explain how images are handled in my blog.

First of all, I am extremely lazy. I hate downloading images off unassumming websites, just to re-upload them into mine. I find this completely unnessary. If we are to steal images, I say, why not do it in style? So I spent hours and hours (ironic huh? lazyness pushing me to work for hours! happens all the time) looking to a plugin that would automatically download remote images. The answer? wp super images.

I know I out moved a lot of you guys. I had been searching for the plugin and most of the forums show unresolved queries for a such and such plugin. I found it. Here it is. I think, it's lack of popularity might be due to its EASL developers, Chinese if I'm right.

So that's one part that's cool! The plugin downloads images from "img" tags and links to images (eg a href equals blah blah). It treats both queries separately too. So if you wanna have a hand on things like me, it'll be easy for you.

Secondly, once you have all your images on your local server (was that a misnomer or whats that you call names for ironic things like huge minitures), you need to make sure they are never too big for your theme. I have nCode Image Resizer for that.

nCode Image Resizer is another awesome simple program. My problem is resizing is done using javascript. That means readers would first download the huge files and then javascript would check them for obesesity and only then will it reduce them. Not good! Now, I remember there was a popular non-wordpress-exclusive script that generates thumbnails off images with width and height arguments. TimThumb. Last night, I decided to write php functions on for my theme that would measure images widths. Once it finds obese pics, it'll make some calculations to find the proper height for the new girth a.k.a BMI and then replace the src links from my image tags to incorporate timthumbs new diet dimensions.

And viola! I can upload as many pics as I want. Pics of all sizes.  And my theme would search them out, weigh them and resize them if neccessary. I'll have a plugin released maybe next week, if time permits.


add_action('the_content', 'JD_treatcontent');

function JD_treatcontent ($the_content) {

//this looks for all img tags from the_content
preg_match_all('/<img[^>]+>/is',$the_content, $result);

//creates two arrays, newimgtags is empty, originalimgtags contains the img tags
$originalimgtags = $result[0];
$newimgtags = array();

//each tag is passthru jd_capimagesize function and results is sent to the empty array newimgtags
foreach ($originalimgtags as $key=>$imgtag) {
$newimgtags[$key] = JD_capimagesize($imgtag);
}

//each instance from the original list of tags is replaced with the new one
$post->post_content = str_replace($originalimgtags,$newimgtags,$the_content);

return $post->post_content;

}

function JD_treatimages ($post_ID) {

$post = get_post($post_ID);
$the_content = $post->post_content;

//this looks for all img tags from the_content
preg_match_all('/<img[^>]+>/is',$the_content, $result);

//creates two arrays, newimgtags is empty, originalimgtags contains the img tags
$originalimgtags = $result[0];
$newimgtags = array();

//each tag is passthru jd_capimagesize function and results is sent to the empty array newimgtags
foreach ($originalimgtags as $key=>$imgtag) {
$newimgtags[$key] = JD_capimagesize($imgtag);
}

//each instance from the original list of tags is replaced with the new one
$post->post_content = str_replace($originalimgtags,$newimgtags,$the_content);

//database is updated
global $wpdb;
$postary=add_magic_quotes(array("content"=>$post->post_content));
$wpdb->query("UPDATE `wp_posts` SET `post_content` = '{$postary["content"]}' WHERE `ID` = '{$post_ID}';");

}

function JD_capimagesize($content) {

//lists arrays of urls, widths and heights
$images=JD_GetImgUrlFromHtml($content,"url");
$widths=JD_GetImgUrlFromHtml($content,"width");
$heights=JD_GetImgUrlFromHtml($content,"height");

//cleans up width and height tags from images, and gets new urls from JD_capimage
$newimages=array();
foreach ($images as $key=>$url)
{
$images[$key]= 'src="'.$images[$key];
$newimages[$key]='src="'.JD_capimage($url);
$widths[$key]= 'width="'.$widths[$key].'"';
$heights[$key]= 'height="'.$heights[$key].'"';
}

//finishes clean up and replaces old url with new ones
$content=str_replace($images,$newimages,$content);
$content=str_replace($widths,'',$content);
$content=str_replace($heights,'',$content);
return $content;
}

function JD_capimage($url) {
$size = getimagesize($url);
$uploads=wp_upload_dir();

if ($size[0] > 500) {
$proportion = 500 / $size[0];
$height = floor($size[1] * $proportion);

$url = get_bloginfo('template_directory') . '/timthumb.php?src=' . $url . '&w=500&h='.$height.'&zc=1';

}
return $url;
}

function JD_savefile($newurl,$filename)
{
$content=@file_get_contents($newurl);

$fp=fopen($filename,"w+");
if (fwrite($fp,$content))
{
fclose($fp);
return $filename;
}
else
{
fclose($fp);
return false;
}
}

function JD_GetImgUrlFromHtml($text,$request)
{
preg_match_all("'<img[^>]*?>'si",$text,$n);
$oldimgsrc=array();
$oldwidth=array();
$oldheight=array();
foreach ($n as $m)
{
foreach ($m as $x)
{
preg_match('#src[[:space:]]*=[[:space:]]*[\'|"]?([[:alnum:]:@/._-]+[?]?[^\'|"]*)"?#ie',$x,$y);
$oldimgsrc[]=$y[1];

preg_match('#width[[:space:]]*=[[:space:]]*[\'|"]?([[:alnum:]:@/._-]+[?]?[^\'|"]*)"?#ie',$x,$y);
$oldwidth[]=$y[1];

preg_match('#height[[:space:]]*=[[:space:]]*[\'|"]?([[:alnum:]:@/._-]+[?]?[^\'|"]*)"?#ie',$x,$y);
$oldheight[]=$y[1];
}
}
switch ($request) {
case "src":
return $oldimgsrc;
break;
case "width":
return $oldwidth;
break;
case "height":
return $oldheight;
break;
}
return $oldimgsrc;
}

Posted on Jul 1, 2010

Splitting XYZ from BlendShape Targets

I was reading an article about an awesome book about facial character setup titled Stop Staring. It's pretty old. Definitely worth the buy!

It describes a method of having to divide the axises of displacement caused by targets.

It works simple. Consider a blendshape deformer that makes a vertex move from point A to point B.

We will instead make 3 versions of the target shape. With each copy containing displacement coming from only one axis.


This step is achieved using a script.

global proc isolateAxisBlend (string $base, string $ini_target, string $axis) {
    $object = `duplicate -n ($ini_target+"_dup_"+$axis) $ini_target`;
    $obj = $object[0];

        for ($i=0;$i<4570;$i++) {
        $xform_base = `xform -q -t ($base+".vtx["+$i+"]")`;
        $xform_obj = `xform -q -t ($obj+".vtx["+$i+"]")`;

        switch ($axis) {
            case "yz" :
                xform -t $xform_base[0] $xform_obj[1] $xform_obj[2] ($obj+".vtx["+$i+"]");
                break;
            case "xz" :
                xform -t $xform_obj[0] $xform_base[1] $xform_obj[2] ($obj+".vtx["+$i+"]");
                break;
            case "xy" :
                xform -t $xform_obj[0] $xform_obj[1] $xform_base[2] ($obj+".vtx["+$i+"]");
                break;
            case "z" :
                xform -t $xform_base[0] $xform_base[1] $xform_obj[2] ($obj+".vtx["+$i+"]");
                break;
            case "x" :
                xform -t $xform_obj[0] $xform_base[1] $xform_base[2] ($obj+".vtx["+$i+"]");
                break;
            case "y" :
                xform -t $xform_base[0] $xform_obj[1] $xform_base[2] ($obj+".vtx["+$i+"]");
                break;
        }

    }

}

Usage: To use this procedure, copy, paste and run it from the script editor to load the procedure into memory. You'll need a base shape and a target shape. In MAYA's MEL command line (or through the script editor), type isolateAxisBlend "nameOfBaseMesh" "nameOfTargetMesh" "axis". For example:

isolateAxisBlend "baseMesh" "targetMesh" "x";
isolateAxisBlend "baseMesh" "targetMesh" "y";
isolateAxisBlend "baseMesh" "targetMesh" "z";

Try this:

  1. Create two polygon spheres named "baseMesh" and "targetMesh".
  2. Select "targetMesh" and go to component mode. Select all vertices and scale it so it is twice bigger in all axises. (Remember to do it in component mode and to not freeze transforms.)
  3. Execute the code in the example above.
  4. There will be three new shapes named "targetMesh_x", "targetMesh_y" and "targetMesh_z". You can delete "targetMesh".
  5. Select "targetMesh_x", "targetMesh_y", "targetMesh_z", and "baseMesh" in that order. We will set up a blendshape node. Go to Animation-->Create Deformers-->Blend Shape.
  6. Create a locator. Select the locator and then the blendshape node. If you followed this tutorial to the letter you can just type the following on MEL command line. "select -r locator1 blendShape1;"
  7. Go to Windows-->General Editors-->Connection Editor. Connect the three axises of translation to the three weights in the blendShape.

Moving the locator would now control all three axises of the target. Verts would no longer move from one point to another, but rather flow the way the animator wants it. On characters, especially facial blends, you get an even bigger variety of targets.

Posted on Jul 1, 2010

Small Developer, Big World

Programming is all around us. Developers fuel the iPhone and it's competition, Android. Developers also are the ones responsible for jailbreaking the iPhone.

We need developers to write programs for our work, for our banks, for the games we play and for movies we watch. Their work is ubiquitos.

And it fattens my heart to know the written word is no longer just a means to communicate between humans, but it is also a means to control applications and, by extension, worlds of organized knowledge.

I am a developer with no formal training. I love it. I breath scripting and taste it in my sweat when I run. And the more I program, the more I realize that everything I've done, doesn't even come close to the world of possibilities. Heck, everything created by all of humanity is still insignificant. Especially in comparison to the bench mark set by reality. Developers can only attempt to go to the correct direction. The feeling is as big as a googolplex.

If you don't already know, a googol is a number starting with one an followed by hundred zeros. Big, huh? A googolplex is another number again starting with one, but this time followed by googol of zeros. A philosopher/scientist once supposed it was practically impossible to write one googolplex on paper because there isn't enough room in this world to fit it in. I think that's dumb. Haha! But the world of possibilities is to me just as big. Carl Sagan wrote in his book, "a googolplex is precisely as far from infinity as is the number one." That's how I feel.

Each language I encounter is a beckon call to attempt the impossible. And yet for every success, you realize that even the word "impossible" is a construct, an ever so elusive construct that will always stay in the horizon of your line of sight no matter how far you run.

I offer this line to the developer community and to the shoes the size of the universe we are trying to fit our shoes in.

print "hello world!";

Posted on Mar 3, 2010

modCharSetup version 1

First release of the modCharSetup (short for Modular Character Setup) for Maya is now available for download. Please peruse modCharSetup 101 to learn how to use it.

To download the file click here:

modCharSetup v1

To install, just unzip the download. Inside you will see a file named autoinstall.cmd. Run this file by double clicking on it. It will install and place all the neccessary scripts in their proper places. In Maya (after a restart, if autoinstall.cmd was invoked while Maya was running), just look for the command line. Make sure you set it to MEL, instead of Python. Type modCharSetup. Press enter. After which you have to type modCharSetupInstall to install icons to the current shelf.

Posted on Mar 3, 2010

modCharSetup (v1) 101

modCharSetup

is a Maya Character Setup set of scripts that allows a rigger to automate the setting up of characters in a manner that is modular. Parts of the character are divided into multiple different parts that are independent on their own. Because of this, creating a character with more than two arms or even arms that aren't connected to the body and instead to the head, probably, has never before been this easy. The entire suite of tools from the script is designed to allow a rigger to finish setting up controls within 30 minutes per character.

1. Create Placers

Step one is create your placers. Placers allows us to input the positions of joints and controllers to Maya without necessarily creating th . Everything will be done automatically by the script. You have three kinds of placers that you could use. Each of th representing a specific kind of setup. The first is the Three Joint Limb. The TJL, is the setup for most limbs. You would typically use this for your arms, legs and other similar body appendages with two segments or three joints. Hence, the name.

Usage: Click on the Three Joint Limb icon. Provide a name for the set up (e.g. rightArm or leftBunnyEar). Then position each placer created where roughly you'd like to have the joints created.


The TJL, when set up, is outfitted with stretch and an ability to blend between FK and IK. It will also have a "pseudo parent" that (aside from housing the attribute that controls the blending between FK and IK) allows us manage the joints and controls associated to the setup.

The next kind of setup is the X-number Joint Limb. The XJL is very similar to the TJL in that it too will have stretch, and FK to IK blending. The only difference is XJL allows you to have a specified number of joints you'd like to have for your set up.

Usage: Click on the X-number Joint Limb icon. Provide a name for the set up (e.g. tentacleA, dragonTail or antennae). Enter the number of joints you'll need for the setup (e.g. 2, 5, 21). Then position each all placers created roughly where you'd like to have the joints and controllers created for you.
The last kind of setup is the Reverse Foot Limb. The RFL is again very similar to the TJL. The first three joints of the RFL works a lot like a regular TJL. The succeeding joints will form a control set up typical to most characters' foot controls.

Usage: Click on the Reverse Foot icon. Provide a name for the set up (e.g. frontLeftHoof or leftLeg). Then position each placer created roughly where you'd like to have the joints created. You can also twist or rotate the bankIn, bankOut and ankle placers, so that the controllers would rotate properly once created.

2. Converting Placers into Setups

Once you've finished creating all your placers, modCharSetup now has most of the information it'll need to generate your character. Your next step is to convert all the placers into their actual setups. But before you do so, it would be a good idea to save a copy of the scene, just so that you'll have something to return to, if later you realize the positions you provided through the placers aren't correct.

Converting placers into their respective setups is very easy. All you need to do is select any placer that belongs to a particular setup and hit the Create From Placer Icon. You can select multiple placers from multiple set ups, if you want. Executing the tool would convert all th automatically for you.

NOTE: Upon using the Create From Placer Tool, you'll see that a bunch of new objects are created in the outliner. If you think it made your scene messy, please do not try cleaning up yet. Don't even rearrange the objects' hierarchies. Keep everything where they are for now. Each node created is important. If you follow the usage of the script all the way until end, you'll see that the modCharSetup is well capable of cleaning up after itself.

3. Good Old parentConstraints

Once all the set ups are created, you'll see that modCharSetup created a couple of things for you. Firstly, on your screen, all your controls are created. Try moving your controllers (most probably IK controllers and pole vectors) and you'll see that everything is set up. Reverse foot controllers all have the necessary attributes that make foot blends and foot placings possible.
Secondly, in your outliner, you'll see what looks like a huge mess of transform nodes created but actually is very orderly. There are sets of transform nodes (or groups) for each entity (or set up) you created. When I say entity, I mean each time you created a set of placers and gave it a name, that's one entity. Each m ber of that entity, will have the name you provided upon creation as the first part of their name.

So all the m bers of an entity will be considered one set.

In each 'set,' there's a transform node with name + "_skinJoints." Like for an example "leftArm_skinJoints". This node will contain all the joints that are for skinning and are associated to leftArm. There will be a transform node with name + "controllers." Like for an example "leftArm_FK_Controllers". This node will contain all the controllers that are for leftArm. There are other groups.

There will be a transform node with only the name you provided. This is a special node. We will call this node a pseudo parent. It is called pseudo parent because it is a fake parent. Move it around, rotate it. You'll notice that it controls the set up that has its namesake. It acts like it is the true parent, even though, looking at the outliner shows it is clearly not.

Whenever we want a certain setup to follow a part of another setup, we make a joint from the other setup control this transform node, usually through a parentConstraint.

For a list of all groups, refer to the table below.

Name Style Example Name
name leftArm
Your "pseudo parent." Contains the FK-IK blend for TJL, XJL and RJL setups. Also serves as parent for th . You constrain this, you properly constrain the "entity".
name + "_skin_GRP" leftArm_skin_GRP
Where all your joints for skinning are found.
name + "_FK_Controllers_GRP" leftArm_FK_Controllers_GRP
Where all your FK controllers are found.
name + "_IK_Controllers_GRP" leftArm_IK_Controllers_GRP
Where all your IK controllers are found.
name + "_RB_Controllers_GRP" ribbonForLeftArm_RB_Controllers_GRP
Where all Controllers for the Ribbon are found.
name + "_refJoint_GRP" ribbonForLeftArm_refJoint_GRP
Where reference joints for the ribbon controls are transferred to.
name + "donotdelete" leftArm_donotdelete
Where extra important stuff are hidden.
name + "donotdeleteribbon" ribbonForLeftArm__donotdeleteribbon
Where extra important stuff specific to ribbons are located.

To do this, select a joint that you would like to serve as a parentConstraint target. Shift select the "pseudo" parent. Go to Animation Set-->Constraints-->Parent Constraint. Try it out. Do this for each setup you wish to be controlled by another. I'll probably have a button for this in the future.

4. Ribbonize, Tie Ups and Hold Ups.

The Ribbonize Tool converts any number of joints and creates a ribbon control setup to live inside th . Ideally, the joints should be from the same hierarchy, but I've tried using this same tool to make ribbons spanning inter-hierarchies and still got to it to work. I'll probably make distinctions in the future for this.

Just note, when you use the Ribbonize Tool, all affected joint hierarchies are transferred to another group called refJoints. You can still use some or all of th in your skinClusters. I wish I could offer a general rule, but these things really differ from case to case.

Usage: Select multiple joints from the same hierarchy. Execute the tool by clicking on it. Enter the name of the ribbon setup when prompted.

The Tie Up tool, as the name att pts to describe, ties everything up to create your character.

Usage: Select multiple objects from all the setups. Make sure at least one node is selected from each setup and no object outside your character is selected. Execute the tool by clicking on it. Enter the name of the character when prompted.

Earlier, I explained that all setups created by the modCharSetup are governed by "pseudo parents". This is a very logical way to create our character. It is limited though in the sense that if there is nothing for the "pseudo parents" to connect to or follow, how then do we control th ? That's where the Hold Up Tool comes in handy. For setups that follow nothing else but the root of your character, you can simply select any control or joint belonging to that setup and execute this tool. You'll be given a controller just for that set up.

Usage: Select multiple controllers from the setups you'd like to hold up. Then Execute this tool by clicking on it. Provide a name for your control when prompted.

More Information

The three tools--Ribbonize, Tie Ups and Hold ups--may be used in any order (after the setups have been created). But ideally, Tie Ups is held until last. Also notice that you could use Ribbonize and Holdups multiple times, but Tie Ups can only be used once per character.

5. Magic Controls

After using the Tie Up Tool, you are done. From this point onwards, everything we do would simply be additional stuff. They are bonuses of a sort. You could skip this part if you want, but let me tell you, this particular step is easy and the returns of which is most rewarding and impressive.

The entire idea behind these magic controls is that you'll have a selection UI similar to the one described in "Fast, Easy, Flexible Selection UI." To do this, you set up controllers that act in a way you'd like your extensions to.

An example of this is to create a curve. Group it. And make its group constrained to the persp camera via a parentConstrarint. Now where ever and how ever you move your persp camera, these controllers would always follow.

Then select the control curve you'd like to have an extension to, like for an example the head control, and then shift select the curve you just created that is following the camera and hit the Magic Control Button.

You'll notice that the extension curve still follows the camera everywhere. But now whenever you select it, you effectively select the head control as well, as if they are one and the same thing.

Posted on Jan 26, 2010

Quickly Batch Mocap Conversion

from blog.ubi.com

In my thrill in the discovery of the mother load of free motioncapture data, I downloaded all the animations, which were made up of ASF files (skeleton setups) and matching AMC files (motion captured animation). The total download was more than 2 gigabytes.

The promised 4 gigabytes might have been due to the multiple versions of the same data. I only downloaded one type. The type I could import into Maya, the ASF's and their matching AMC's filetypes. Converting these files meant using programs already made available by CMU from their website. There are two DOS executable files available for download. The first is asf2mel.exe which converts ASF files into a MEL script that builds a joint hierarchy for you. The second is amc2mov.exe which creates another MEL script that sets up the joint hierarchy just created to accept the animation contained in the second file, an MOV.

The commands to use the two files are easy to learn. To learn, just peruse the documentation page from MCU mocap lib. You won't have a hard time. The only difficulty I had was the 2,500+ files I wanted to convert. I knew there was no way in hell I'd be typing commands 2.5 thousands times.

Instead I developed a batch sequence that would, in a sense, scan the its own folder for ASF files (files containing skeletons) and then scan the same folder for matching AMC files (files containing motion) and convert them, plus segregate them into folders. Took me about 30 minutes figuring the nine-line script out. But it was well worth it. The computer worked for me for the next three hours converting file after file.

If you downloaded a bunch of ASF files and AMC files from CMU Mo-Cap Library and you want to be able to convert them as fast as I did, you can download the script I made here. All you need to do is make sure the all the files from the zip are contained within the same folder where your ASF and AMC files are. Run conversionbatch.cmd. And viola. Sit and watch your subfolders populate and fillup with free mocap goodness. (BTW, neglect the other CMD file. movconversionbatch.cmd is being executed by conversionbatch.cmd as a nested command.)

Posted on Oct 12, 2009

Fast, Easy, Flexible UI

extremely_old_ui

User Interfaces has been around for decades. For a while we had been using text input UI's. There was a huge following for the voice-activated UI's. But the most prevalent and most used UI is the graphic UI. People have been reinventing it ever since it's first conception.

So much so that it has been held in heavy regard that UI's can make or break an OS; and we've seen this happen time and again. UI's also make or break game consoles, even games themselves. I would even go as far as to say (without valid citations) that development for the, CG and UI, should have and have been going hand in hand. (This guy here, Renato Polimeno, has a list of UI's he compiled from the web in his website.)So wouldn't it be funny if our rigs would be using primitive UI's? Aha! I developed a script that automates a system to create a UI for any Maya rig. The method is very promising, and I am here to share it to everyone. As a disclaimer, allow me to just say, the technology is old. I just developed new way to use old methods. As a testament to its simplicity a script could be written to automate the process for just 15 lines. It can even be shorter. But it is the methods behind that I would like to share here. Hopefully, you guys would appreciate it and start using it with your rigs. And since it is so easy, you might even consider adding UIs to rigs that you don't own.

Here is an example of a UI that you could create using this tutorial as a guide. You could design your UI in any way you deem fit. Allow nothing but your creativity to limit you. The idea is that controls should be easily accessible at all times or at least much of the time. UIs are great but are hard to create. This method would make it easy.

There is just two basic tools that Maya already offers that we shall exploit to get the results that we want. The first is the parent command. The same procedure being activated whenever you press on the p key. The difference is we run it with flags to make sure it works on shape nodes instead of just transform nodes' hieirarchy. We could therefore have extension shapes for any control.

The line to use is 'parent -add -shape shapename'. You can enter the command while an object where you want to add a shape name is already selected. You can include names, a name of a list of names of shape nodes you wish to add followed by the transform node you want to add it to, after the command to be explicit.

The next tool we wish to exploit from Maya, believe it or not, is blendshapes. Blendshapes allow us to make a base object shape blend into the target shapes. Normally, blendshapes are set to local mode, which means it will ignore differences in position, rotation and scale between the base object and target objects. For facial animation setups, this is what we normally use. There is another mode though, that has been forgotten for lack of a genuine practical usage and that is setting the mode to world. This will make your base mesh blend into its target mesh, taking into account any differences in position, rotation and scale. This is what we want and what we will use.

So in effect, what we are trying to do here, is 1) add an extension shape to the controllers that we want to be able to control. Then, 2) we give these extra shapes blendshapes in world mode. These extra shapes would then follow the shape of their targets, while also following their size, position and orientation. And true to the nature of any extra shape node for any transform node, clicking or selecting it would be just as if you selected the transform node.

If you prefer seeing a step by step for this tutorial, minus explanations, follow these:

  1. Create a curves and shape them according to how you'd like your interface to look like.
  2. Duplicate the curve. For this tutorial's purposes, rename it to "duplicateCurve", but you could give it any name you want so long as when I refer to a curve you duplicated, you know that it is that curve that we mean.
  3. Get the name of the shape associated to the duplicate curve (we talked about this). Normally, it's the name of the curve with the word "shape" suffixed to the it (e.g. duplicateCurveShape). In the Attribute editor, it's usually the tab right next to your objects (transform) tab. In the channel editor, it is the name of the next section immediately after your visibility attribute/channel. In the outliner, if you click on display and turn on shapes, uncollapsing objects would reveal shapes associated to them.
  4. Select the control you would like to add the extension shape to. Enter this command (sorry, there is no tool-based alternative to this.) parent -add -shape [shapename]; (e.g. parent -add -shape "duplicateCurveShape"; )
  5. Delete the duplicate curve (e.g. duplicateCurve). Now if you check the outliner, under the control curve where you wanted to add a shape to, there is another shape. It is the shape you added. You successfully transferred the duplicate shape unto the control you are adding an extension to.
  6. Select the shape node of the curve you created in step 1. This is best done through the use of the outliner.
  7. Shift+select the shape node of the curve you added in step 4. Again, this is best done through the use of the outliner.
  8. Go to [Animation] Create Deformers->Blend Shape.
  9. Select the blendShape transform node.
  10. Go to the Attribute Editor. Set all weights to 1.000. Set origin method to world.
  11. Set the visibility of the shape you created to off.

Note: You can have anything happen to the curve you created. You could make it change shape with more blendshapes that are also driven by the control object. You could constrain it to the camera. You could give it set driven keys so that they would change according proximity of objects to each other.

If you would like to see a script, that does this exactly, run this:

global proc specialControls () {
	$selectionList = `ls -sl -type transform`;

	$selectionSize = `size $selectionList`;

	string $selListShapeEquivalent[];

	for ($i = 0; $i < $selectionSize; $i++) {
		select -r $selectionList[$i];

		select -hi;

		$listOfShapes = `ls -sl -type shape`;

		$selListShapeEquivalent[$i] = $listOfShapes[0];
	}

	for ($i = 1; $i < $selectionSize; $i++) {
		$duplicateObj = `duplicate -name ($selectionList[$i]+"duplicate")  $selectionList[$i] `;

		select -r $duplicateObj;
		select -hi; $duplicateShape = `ls -sl -type shape`;

		parent -add -shape $duplicateShape $selectionList[0];

		delete $duplicateObj;

		blendShape -origin world -weight 0 1 $selListShapeEquivalent[$i] $duplicateShape;
		setAttr  ($selectionList[$i]+".v") 0;
	}
}

Now, all you need to do is run the command specialControls, while having two or more objects selected. The first object being the control you'd like add curves to.

This here is another way of applying this method--taking it to the next level. It was an attempt (successful to my surprise) to emulate the same effect that Paolo Dominici had for his control free rig that could be viewed here. As a disclaimer: I did not intend the script to accomplish something like this. But it works! Check it out and see if you could think of ways to use it for other mind bogging creations.

These are the steps:

  1. You’ll need to acquire a ready working rig.
  2. Select the mesh. Apply a ‘duplicate special’ on it, making sure you have “Duplicate input connections” enabled. Make as many duplicates as the controls that you’ll have to replace.
  3. These duplicates should react exactly like how the original was moving. Test this by moving controllers. Make sure the duplicates are following the original exactly.
  4. Delete faces from the duplicates, leaving only faces that you would represent the control you are making. Make sure you have Construction history turned on.
  5. Select the control. Shift-select the duplicated mesh (with deleted faces).  Run the script.
  6. Put the original mesh in a layer that set to Referenced.
  7. Repeat steps 4-6 for each duplicate/control curve.

NOTE: In copying the lines of the code from my notepad, I somehow missed a line. $selectionSize = `size $selectionList`; It's the second line of the procedure. Thanks to Johnny Z for pointing this out to me.

This tutorial also @ creativecrash.

62 SQL queries have been executed to show this page