Saturday, January 5, 2013


addMarkersJointsToVerts.mel - Here is a little script that I hacked together, it will allow you to take a selection of verts from a model and build a marker and joint that will follow that vert where ever it goes on the surface of the source mesh. So you could make blendshapes with a mesh and attach buttons, eyelashes or whatever you like. (It is basically a rivet system) It uses Maya particle emitters as the follow point. You could also use this with a simple ncloth mesh and bake out the animation onto the provided joints that you are using. Or you could do something like dynamically driven rope. So I will provide the script below, please don't laugh at my scripting abilities...I hacked this together...My hope is that one of you smart maya mel/python people could clean this up and make it into something even cooler. (Thanks for those who tried to help me with the string renaming process...still don't fully have that figured out. So the script isn't as smart as I would like it to be.)

I will add the scripts in the comments section of this post. 
Let me know if this helps you in anyway! :)


NickZ. said...

Take this script, copy it into the script editor in a mel tab. Then select all the verts that you want to run the script on, select all the text in the script window and hit ctrl +enter. This will run the script and set everything up.


// This script will select a vert on a model and add an emitter and a marker to the object.
// This will take a selection of verts and make and turn it into a string/list. -fl flag is added to deal with the verts, this way it will seperate everything out so we can do an operation on each vert.

string $sel[] = `ls -fl -sl`;
string $obj;

// This will set up a loop for us to use.

for ($obj in $sel)

select $obj;

// Rename strings

string $emitterRename = ($obj +"emitter");
string $normalConstraintRename = ($obj +"normConstraint");

print $emitterRename;
print $normalConstraintRename;

// Make the emitter

emitter -type omni -r 100 -sro 0 -nuv 0 -cye none -cyi 1 -spd 1 -srn 0 -nsp 1 -tsp 0 -mxd 0 -mnd 0 -dx 1 -dy 0 -dz 0 -sp 0 -n emitter;

// Make the nurbs spheres
// If you want to change the size of the spheres, change the number after -r

sphere -p 0 0 0 -ax 0 1 0 -ssw 0 -esw 360 -r .1 -d 3 -ut 0 -tol 0.01 -s 2 -nsp 2 -ch 1 -n marker_CTRL;objectMoveCommand;
setDisplaySmoothness 3;

// Create a joint for each marker. These Joints will follow the markers due to the parent constraint we are about to make.
// If you want to change the joint radius, change the number after "joint.radius"

joint -p 0 0 0 -n joint_ -rad .05;

select -cl ;

// objExists will return true or false (1 or 0), so you can use it multiple ways.

int $objTest = `objExists rootJointWorld` ;

// If that object exists, it will return 1 (true), so then you could say something like:

if($objTest == 1) {
print "It Exists!" ;
else {
// This will create a joint at the world orient, all other joints will be parented to this joint.
// -n will allow us to name the joint, and -rad will let us set the radius for the joint.
joint -p 0 0 0 -n rootJointWorld -rad .2;

select -r joint_ rootJointWorld;

select -r marker_CTRL joint_;
parentConstraint -weight 1;

select -cl ;

select -r joint_;

rename "joint_" "joint_000";

// Create marker group

select -r marker_CTRL;
group -em -n marker_CTRL_Group; xform -os -piv 0 0 0 ;

// Parent the marker to the group

select -r marker_CTRL marker_CTRL_Group;

// Point constrain the marker group to the emitter

select -r "emitter" marker_CTRL_Group;
pointConstraint -weight 1;

// Normal constrain the marker group to the object

select -r $obj marker_CTRL_Group;
normalConstraint -weight 1 -aimVector 0 1 0 -upVector 0 1 0 -worldUpType "vector" -worldUpVector 0 1 0 -n $normalConstraintRename;

// Rename the parts

rename "marker_CTRL" "marker_CTRL_";
rename "emitter" $emitterRename;
rename "marker_CTRL_Group" "marker_CTRL_Group_";

//end of the loop


// Group the markers

select -r "marker_CTRL_Group_*";
group -n marker_CTRL_GROUPS; xform -os -piv 0 0 0;

// Groups all the emitters into a set.

select -r -ne "emitterSet*";
$createSetResult = `sets -name emitterSets_ALL`;
select -cl ;

Gabriela Araujo said...

Your script almost perform the functionality what I need. But instead of vertex, I want to select locators.

I'm doing that because I have some facial mocap data in those locators.

I'm new in MEL, and I've trying to figure this out since yesterday.

Unknown said...

I baked an Ntloth but the Joints does not follow the animated vertex, what did I did wrong?

Unknown said...

can we put those joints and follow an added follicles in each vertex_? Im trying to pas the geometry and the joints animated to Unity...

NickZ. said...

I would try the set up on something simple like a cube or sphere, make sure the functionality is still there, just want to make sure that nothing changed in Maya. If everything still works on the simple geo then you should be able to do a set up where you drive ncloth, may need ncloth to drive a simple cage geo and then these joints are attached to that simulated piece of geo. You then need game geo hat is weighted to these joints and the you can push the results to unity or unreal.

Samuel Daniel said...

Reuben Debono - 4 years ago


Maybe this will help to automate the process.
replace pCube1 with name of your object and then select the vertices and run the script. Enjoy :)

//Joints on Vertices Tool

proc vrtJnt(){

//Query vertex selection
string $selVerts[] = `ls -sl -fl`;

//For Loop - applies the command to each selected vertex
for ($vrts in $selVerts){

//select each vertex individually
select $vrts;
//create a cluster on each selected vertex
string $cl[] = `newCluster " -relative -envelope 1"`;
//clear selection so joint is not parented under cluster
select -cl;
//create a joint
string $jnt = `joint`;
//point constrain the joint TO the cluster
string $ptCnJnt[] = `pointConstraint -offset 0 0 0 -weight 1 $cl $jnt`;
//Query the point constrain tied to the joint
string $findPtCn[] = `listRelatives -typ pointConstraint $jnt`;
//select and delete the joint's point constrain
select $findPtCn[0]; doDelete;
//select and delete the cluster
select -replace $cl; doDelete;

select $vrts;
$uvMap = `polyListComponentConversion -fv -tuv`;
float $uv[2]=`polyEditUV -q $uvMap`;

select $vrts $jnt;
doCreatePointOnPolyConstraintArgList 2 { "0" ,"0" ,"0" ,"1" ,"" ,"1" ,"0" ,"0" ,"0" ,"0" };
{string $constraint[]=`pointOnPolyConstraint -offset 0 0 0 -weight 1`; setAttr ($constraint[0]+".pCube1U0") $uv[0]; setAttr ($constraint[0]+".pCube1V0") $uv[1];};

//run the procedure

Link to the Youtube Video -