PDA

View Full Version : Blend To Comprehend

 qkuotidian01-12-2011, 09:21 AMHi, Is it possible to create blend between several shapes? The goal is to create blends, which would reflect changes of the targets. So if any further changes are made, blends in between would update – for example, if 2 vertices on the target have been moved, and the field is reflecting this change (which of course did not happen my handmade case). I think it can be done through baking blend shapes at various frames, but I have absolutely no knowledge of animation and the script needed urgently. Long time ago I found that script – but it has the same problem as my handmade version has – blends do not reflect changes in targets… proc jooRequestedBlendField(int \$xSteps,int \$ySteps){ \$selection=`ls -sl`; if (size(\$selection)!=4) //sanity check print "please select 4 objects clockwise"; \$nuSel=`duplicate`; group; makeIdentity -apply true -t 1 -r 1 -s 1 -n 0 \$nuSel; \$toCopy=`duplicate \$nuSel[3]`; \$nuSel[4]=\$toCopy[0]; \$blend=`blendShape \$nuSel`; \$xSteps--; \$ySteps--; for(\$i=0;\$i<=\$xSteps;\$i++){ for(\$j=0;\$j<=\$ySteps;\$j++){ setAttr (\$blend[0]+"."+\$nuSel[2]) ((\$i/(float)\$xSteps)*(1-(\$j/(float)\$ySteps))); setAttr (\$blend[0]+"."+\$nuSel[3]) ((1-(\$i/(float)\$xSteps)*(1-(\$j/(float)\$ySteps)))); setAttr (\$blend[0]+"."+\$nuSel[1]) ((\$i/(float)\$xSteps)*(\$j/(float)\$ySteps)); setAttr (\$blend[0]+"."+\$nuSel[0]) ((1-(\$i/(float)\$xSteps))*(\$j/(float)\$ySteps)); duplicate \$toCopy[0]; } } delete \$nuSel; // optional cleanup uncomment to delete originals // delete \$selection; } // select 4 objects clockwise and run // set numbers to match how many you need jooRequestedBlendField(6,7); I WILL APPRECIATE YOUR HELP!
qkuotidian
01-12-2011, 09:10 PM
more than 500 people visited that page - and no one knows

pixelranger
01-12-2011, 10:46 PM
That script just makes a duplicate pillar, makes the originals blendshapes targets and then goes through interpolated weight combinations (basically "walking through" the different pillar positions by changing blend weights) and duplicating along the way, leaving behind a trail (and at the end, a matrix) of pillars duplicated at different weight settings.
To make them "remember" their targets you have to actually create blend shapes for them for every time in the loop (since they never had blendshapes, they are just bi-products of the first duplicate's "walk" through blendshape weights.
Also, since the script freezes transforms, you either have to create the blend shapes first (before moving them away from the origin), or even better: don't freeze transformation).

What you want to do, is create a blend shape for each copy (original pillars as targets, new duplicate as blend object).
And if you declare your weights at the start of the loop, you can use them for a lot of things (keeping the position, rotation and scale connected (with offsets) to the originals etc...):

for( \$i=0; \$i<=\$xSteps; \$i++ ){
for( \$j=0; \$j<= \$ySteps; \$j++ ){
float \$w0 = ((1-(\$i/(float)\$xSteps))*(\$j/(float)\$ySteps));
float \$w1 = ((\$i/(float)\$xSteps)*(\$j/(float)\$ySteps));
float \$w2 = ((\$i/(float)\$xSteps)*(1-(\$j/(float)\$ySteps)));
float \$w3 = ((1-(\$i/(float)\$xSteps)*(1-(\$j/(float)\$ySteps))));

pixelranger
01-13-2011, 12:25 AM
Here the copies get set up with multiplyDivide/plusMinusAverageNodes, so you can translate/rotate/scale the originals as well as deform them (they are still setup as blend shapes.

I am having some problems with the initialization, though, because I seem to get an offset that I don't want....

proc interpArrayField(int \$xSteps,int \$ySteps){
string \$sel[] =`ls -sl`;
if (size(\$sel)!=4){
print "please select 4 objects clockwise";
}else{
float \$pos0[] = `getAttr (\$sel[0] + ".translate")`;
float \$pos1[] = `getAttr (\$sel[1] + ".translate")`;
float \$pos2[] = `getAttr (\$sel[2] + ".translate")`;
float \$pos3[] = `getAttr (\$sel[3] + ".translate")`;

float \$rot0[] = `getAttr (\$sel[0] + ".rotate")`;
float \$rot1[] = `getAttr (\$sel[1] + ".rotate")`;
float \$rot2[] = `getAttr (\$sel[2] + ".rotate")`;
float \$rot3[] = `getAttr (\$sel[3] + ".rotate")`;

float \$scale0[] = `getAttr (\$sel[0] + ".scale")`;
float \$scale1[] = `getAttr (\$sel[1] + ".scale")`;
float \$scale2[] = `getAttr (\$sel[2] + ".scale")`;
float \$scale3[] = `getAttr (\$sel[3] + ".scale")`;

\$newSel=`duplicate`;
string \$group = `group -n "matrixGroup"`;

for(\$i=0;\$i<=\$xSteps;\$i++){
for(\$j=0;\$j<=\$ySteps;\$j++){
float \$w0 = ((\$i/(float)\$xSteps)*(1-(\$j/(float)\$ySteps)));
float \$w1 = ((\$i/(float)\$xSteps)*(\$j/(float)\$ySteps));
float \$w2 = ((1-(\$i/(float)\$xSteps))*(\$j/(float)\$ySteps));
float \$w3 = ((1-(\$i/(float)\$xSteps)*(1-(\$j/(float)\$ySteps))));

string \$newObject[] = `duplicate \$newSel[3]`;
string \$blendS[] = `blendShape \$sel \$newObject`;

string \$pos0Mult = `createNode multiplyDivide -n (\$sel[0] + "_posMult")`;
connectAttr -f (\$sel[0] + ".translate") (\$pos0Mult + ".input1");
setAttr (\$pos0Mult + ".input2X") \$w0;
setAttr (\$pos0Mult + ".input2Y") \$w0;
setAttr (\$pos0Mult + ".input2Z") \$w0;
string \$pos1Mult = `createNode multiplyDivide -n (\$sel[1] + "_posMult")`;
connectAttr -f (\$sel[1] + ".translate") (\$pos1Mult + ".input1");
setAttr (\$pos1Mult + ".input2X") \$w1;
setAttr (\$pos1Mult + ".input2Y") \$w1;
setAttr (\$pos1Mult + ".input2Z") \$w1;
string \$pos2Mult = `createNode multiplyDivide -n (\$sel[2] + "_posMult")`;
connectAttr -f (\$sel[2] + ".translate") (\$pos2Mult + ".input1");
setAttr (\$pos2Mult + ".input2X") \$w2;
setAttr (\$pos2Mult + ".input2Y") \$w2;
setAttr (\$pos2Mult + ".input2Z") \$w2;
string \$pos3Mult = `createNode multiplyDivide -n (\$sel[3] + "_posMult")`;
connectAttr -f (\$sel[3] + ".translate") (\$pos3Mult + ".input1");
setAttr (\$pos3Mult + ".input2X") \$w3;
setAttr (\$pos3Mult + ".input2Y") \$w3;
setAttr (\$pos3Mult + ".input2Z") \$w3;

string \$rot0Mult = `createNode multiplyDivide -n (\$sel[0] + "_rotMult")`;
connectAttr -f (\$sel[0] + ".rotate") (\$rot0Mult + ".input1");
setAttr (\$rot0Mult + ".input2X") \$w0;
setAttr (\$rot0Mult + ".input2Y") \$w0;
setAttr (\$rot0Mult + ".input2Z") \$w0;
string \$rot1Mult = `createNode multiplyDivide -n (\$sel[1] + "_rotMult")`;
connectAttr -f (\$sel[1] + ".rotate") (\$rot1Mult + ".input1");
setAttr (\$rot1Mult + ".input2X") \$w1;
setAttr (\$rot1Mult + ".input2Y") \$w1;
setAttr (\$rot1Mult + ".input2Z") \$w1;
string \$rot2Mult = `createNode multiplyDivide -n (\$sel[2] + "_rotMult")`;
connectAttr -f (\$sel[2] + ".rotate") (\$rot2Mult + ".input1");
setAttr (\$rot2Mult + ".input2X") \$w2;
setAttr (\$rot2Mult + ".input2Y") \$w2;
setAttr (\$rot2Mult + ".input2Z") \$w2;
string \$rot3Mult = `createNode multiplyDivide -n (\$sel[3] + "_rotMult")`;
connectAttr -f (\$sel[3] + ".rotate") (\$rot3Mult + ".input1");
setAttr (\$rot3Mult + ".input2X") \$w3;
setAttr (\$rot3Mult + ".input2Y") \$w3;
setAttr (\$rot3Mult + ".input2Z") \$w3;

string \$scale0Mult = `createNode multiplyDivide -n (\$sel[0] + "_rotMult")`;
connectAttr -f (\$sel[0] + ".scale") (\$scale0Mult + ".input1");
setAttr (\$scale0Mult + ".input2X") \$w0;
setAttr (\$scale0Mult + ".input2Y") \$w0;
setAttr (\$scale0Mult + ".input2Z") \$w0;
string \$scale1Mult = `createNode multiplyDivide -n (\$sel[1] + "_rotMult")`;
connectAttr -f (\$sel[1] + ".scale") (\$scale1Mult + ".input1");
setAttr (\$scale1Mult + ".input2X") \$w1;
setAttr (\$scale1Mult + ".input2Y") \$w1;
setAttr (\$scale1Mult + ".input2Z") \$w1;
string \$scale2Mult = `createNode multiplyDivide -n (\$sel[2] + "_rotMult")`;
connectAttr -f (\$sel[2] + ".scale") (\$scale2Mult + ".input1");
setAttr (\$scale2Mult + ".input2X") \$w2;
setAttr (\$scale2Mult + ".input2Y") \$w2;
setAttr (\$scale2Mult + ".input2Z") \$w2;
string \$scale3Mult = `createNode multiplyDivide -n (\$sel[3] + "_rotMult")`;
connectAttr -f (\$sel[3] + ".scale") (\$scale3Mult + ".input1");
setAttr (\$scale3Mult + ".input2X") \$w3;
setAttr (\$scale3Mult + ".input2Y") \$w3;
setAttr (\$scale3Mult + ".input2Z") \$w3;

string \$posSum = `createNode plusMinusAverage -n "posSum"`;
connectAttr -f ( \$pos0Mult + ".output") ( \$posSum + ".input3D[0]");
connectAttr -f ( \$pos1Mult + ".output") ( \$posSum + ".input3D[1]");
connectAttr -f ( \$pos2Mult + ".output") ( \$posSum + ".input3D[2]");
connectAttr -f ( \$pos3Mult + ".output") ( \$posSum + ".input3D[3]");
connectAttr -f ( \$posSum + ".output3D") ( \$newObject[0] + ".translate");

string \$rotSum = `createNode plusMinusAverage -n "rotSum"`;
connectAttr -f ( \$rot0Mult + ".output") ( \$rotSum + ".input3D[0]");
connectAttr -f ( \$rot1Mult + ".output") ( \$rotSum + ".input3D[1]");
connectAttr -f ( \$rot2Mult + ".output") ( \$rotSum + ".input3D[2]");
connectAttr -f ( \$rot3Mult + ".output") ( \$rotSum + ".input3D[3]");
connectAttr -f ( \$rotSum + ".output3D") ( \$newObject[0] + ".rotate");

string \$scaleSum = `createNode plusMinusAverage -n "scaleSum"`;
connectAttr -f ( \$scale0Mult + ".output") ( \$scaleSum + ".input3D[0]");
connectAttr -f ( \$scale1Mult + ".output") ( \$scaleSum + ".input3D[1]");
connectAttr -f ( \$scale2Mult + ".output") ( \$scaleSum + ".input3D[2]");
connectAttr -f ( \$scale3Mult + ".output") ( \$scaleSum + ".input3D[3]");
connectAttr -f ( \$scaleSum + ".output3D") ( \$newObject[0] + ".scale");

setAttr (\$blendS[0]+"."+\$sel[0]) \$w0;
setAttr (\$blendS[0]+"."+\$sel[1]) \$w1;
setAttr (\$blendS[0]+"."+\$sel[2]) \$w2;
setAttr (\$blendS[0]+"."+\$sel[3]) \$w3;

}
}
delete \$newSel;
}
}

interpArrayField(6,7);

Any mathematicians out there? haha this is reeeallly annoying.
The first three objects seem fine when I move them . The interpolation works fine, I mean. But when I move number 4 something isn't right. It's like the array is following the opposite diagonal corner to much...
Any ideas?

pixelranger
01-13-2011, 12:48 AM
ah \$w3 was wrong. Probably a copy/paste error.

Now it is deform and translation compatible:

proc interpArrayField(int \$xSteps,int \$ySteps){
string \$sel[] =`ls -sl`;
if (size(\$sel)!=4){
print "please select 4 objects clockwise";
}else{
float \$pos0[] = `getAttr (\$sel[0] + ".translate")`;
float \$pos1[] = `getAttr (\$sel[1] + ".translate")`;
float \$pos2[] = `getAttr (\$sel[2] + ".translate")`;
float \$pos3[] = `getAttr (\$sel[3] + ".translate")`;

float \$rot0[] = `getAttr (\$sel[0] + ".rotate")`;
float \$rot1[] = `getAttr (\$sel[1] + ".rotate")`;
float \$rot2[] = `getAttr (\$sel[2] + ".rotate")`;
float \$rot3[] = `getAttr (\$sel[3] + ".rotate")`;

float \$scale0[] = `getAttr (\$sel[0] + ".scale")`;
float \$scale1[] = `getAttr (\$sel[1] + ".scale")`;
float \$scale2[] = `getAttr (\$sel[2] + ".scale")`;
float \$scale3[] = `getAttr (\$sel[3] + ".scale")`;

\$newSel=`duplicate`;
string \$group = `group -n "matrixGroup"`;

for(\$i=0;\$i<=\$xSteps;\$i++){ // \$i=5; \$j=3; \$xSteps = \$ySteps = 7;
for(\$j=0;\$j<=\$ySteps;\$j++){
float \$w0 = ((\$i/(float)\$xSteps)*(1-(\$j/(float)\$ySteps)));
float \$w1 = ((\$i/(float)\$xSteps)*(\$j/(float)\$ySteps));
float \$w2 = ((1-(\$i/(float)\$xSteps))*(\$j/(float)\$ySteps));
float \$w3 = ((1-(\$i/(float)\$xSteps))*(1-(\$j/(float)\$ySteps)));

string \$newObject[] = `duplicate \$newSel[0]`;
string \$blendS[] = `blendShape \$sel \$newObject`;

string \$pos0Mult = `createNode multiplyDivide -n (\$sel[0] + "_posMult")`;
connectAttr -f (\$sel[0] + ".translate") (\$pos0Mult + ".input1");
setAttr (\$pos0Mult + ".input2X") \$w0;
setAttr (\$pos0Mult + ".input2Y") \$w0;
setAttr (\$pos0Mult + ".input2Z") \$w0;
string \$pos1Mult = `createNode multiplyDivide -n (\$sel[1] + "_posMult")`;
connectAttr -f (\$sel[1] + ".translate") (\$pos1Mult + ".input1");
setAttr (\$pos1Mult + ".input2X") \$w1;
setAttr (\$pos1Mult + ".input2Y") \$w1;
setAttr (\$pos1Mult + ".input2Z") \$w1;
string \$pos2Mult = `createNode multiplyDivide -n (\$sel[2] + "_posMult")`;
connectAttr -f (\$sel[2] + ".translate") (\$pos2Mult + ".input1");
setAttr (\$pos2Mult + ".input2X") \$w2;
setAttr (\$pos2Mult + ".input2Y") \$w2;
setAttr (\$pos2Mult + ".input2Z") \$w2;
string \$pos3Mult = `createNode multiplyDivide -n (\$sel[3] + "_posMult")`;
connectAttr -f (\$sel[3] + ".translate") (\$pos3Mult + ".input1");
setAttr (\$pos3Mult + ".input2X") \$w3;
setAttr (\$pos3Mult + ".input2Y") \$w3;
setAttr (\$pos3Mult + ".input2Z") \$w3;

string \$rot0Mult = `createNode multiplyDivide -n (\$sel[0] + "_rotMult")`;
connectAttr -f (\$sel[0] + ".rotate") (\$rot0Mult + ".input1");
setAttr (\$rot0Mult + ".input2X") \$w0;
setAttr (\$rot0Mult + ".input2Y") \$w0;
setAttr (\$rot0Mult + ".input2Z") \$w0;
string \$rot1Mult = `createNode multiplyDivide -n (\$sel[1] + "_rotMult")`;
connectAttr -f (\$sel[1] + ".rotate") (\$rot1Mult + ".input1");
setAttr (\$rot1Mult + ".input2X") \$w1;
setAttr (\$rot1Mult + ".input2Y") \$w1;
setAttr (\$rot1Mult + ".input2Z") \$w1;
string \$rot2Mult = `createNode multiplyDivide -n (\$sel[2] + "_rotMult")`;
connectAttr -f (\$sel[2] + ".rotate") (\$rot2Mult + ".input1");
setAttr (\$rot2Mult + ".input2X") \$w2;
setAttr (\$rot2Mult + ".input2Y") \$w2;
setAttr (\$rot2Mult + ".input2Z") \$w2;
string \$rot3Mult = `createNode multiplyDivide -n (\$sel[3] + "_rotMult")`;
connectAttr -f (\$sel[3] + ".rotate") (\$rot3Mult + ".input1");
setAttr (\$rot3Mult + ".input2X") \$w3;
setAttr (\$rot3Mult + ".input2Y") \$w3;
setAttr (\$rot3Mult + ".input2Z") \$w3;

string \$scale0Mult = `createNode multiplyDivide -n (\$sel[0] + "_rotMult")`;
connectAttr -f (\$sel[0] + ".scale") (\$scale0Mult + ".input1");
setAttr (\$scale0Mult + ".input2X") \$w0;
setAttr (\$scale0Mult + ".input2Y") \$w0;
setAttr (\$scale0Mult + ".input2Z") \$w0;
string \$scale1Mult = `createNode multiplyDivide -n (\$sel[1] + "_rotMult")`;
connectAttr -f (\$sel[1] + ".scale") (\$scale1Mult + ".input1");
setAttr (\$scale1Mult + ".input2X") \$w1;
setAttr (\$scale1Mult + ".input2Y") \$w1;
setAttr (\$scale1Mult + ".input2Z") \$w1;
string \$scale2Mult = `createNode multiplyDivide -n (\$sel[2] + "_rotMult")`;
connectAttr -f (\$sel[2] + ".scale") (\$scale2Mult + ".input1");
setAttr (\$scale2Mult + ".input2X") \$w2;
setAttr (\$scale2Mult + ".input2Y") \$w2;
setAttr (\$scale2Mult + ".input2Z") \$w2;
string \$scale3Mult = `createNode multiplyDivide -n (\$sel[3] + "_rotMult")`;
connectAttr -f (\$sel[3] + ".scale") (\$scale3Mult + ".input1");
setAttr (\$scale3Mult + ".input2X") \$w3;
setAttr (\$scale3Mult + ".input2Y") \$w3;
setAttr (\$scale3Mult + ".input2Z") \$w3;

string \$posSum = `createNode plusMinusAverage -n "posSum"`;
connectAttr -f ( \$pos0Mult + ".output") ( \$posSum + ".input3D[0]");
connectAttr -f ( \$pos1Mult + ".output") ( \$posSum + ".input3D[1]");
connectAttr -f ( \$pos2Mult + ".output") ( \$posSum + ".input3D[2]");
connectAttr -f ( \$pos3Mult + ".output") ( \$posSum + ".input3D[3]");
connectAttr -f ( \$posSum + ".output3D") ( \$newObject[0] + ".translate");

string \$rotSum = `createNode plusMinusAverage -n "rotSum"`;
connectAttr -f ( \$rot0Mult + ".output") ( \$rotSum + ".input3D[0]");
connectAttr -f ( \$rot1Mult + ".output") ( \$rotSum + ".input3D[1]");
connectAttr -f ( \$rot2Mult + ".output") ( \$rotSum + ".input3D[2]");
connectAttr -f ( \$rot3Mult + ".output") ( \$rotSum + ".input3D[3]");
connectAttr -f ( \$rotSum + ".output3D") ( \$newObject[0] + ".rotate");

string \$scaleSum = `createNode plusMinusAverage -n "scaleSum"`;
connectAttr -f ( \$scale0Mult + ".output") ( \$scaleSum + ".input3D[0]");
connectAttr -f ( \$scale1Mult + ".output") ( \$scaleSum + ".input3D[1]");
connectAttr -f ( \$scale2Mult + ".output") ( \$scaleSum + ".input3D[2]");
connectAttr -f ( \$scale3Mult + ".output") ( \$scaleSum + ".input3D[3]");
connectAttr -f ( \$scaleSum + ".output3D") ( \$newObject[0] + ".scale");

setAttr (\$blendS[0]+"."+\$sel[0]) \$w0;
setAttr (\$blendS[0]+"."+\$sel[1]) \$w1;
setAttr (\$blendS[0]+"."+\$sel[2]) \$w2;
setAttr (\$blendS[0]+"."+\$sel[3]) \$w3;

}
}
delete \$newSel;
}
}

interpArrayField(6,7);

qkuotidian
01-13-2011, 05:56 AM
andrehitsoy,
you script is fantastic!
So much to learn from it…

pixelranger
01-13-2011, 11:41 AM
Thanks, but its these 6 lines of code that does the magic:

for(\$i=0;\$i<=\$xSteps;\$i++){
for(\$j=0;\$j<=\$ySteps;\$j++){
float \$w0 = ((\$i/(float)\$xSteps)*(1-(\$j/(float)\$ySteps)));
float \$w1 = ((\$i/(float)\$xSteps)*(\$j/(float)\$ySteps));
float \$w2 = ((1-(\$i/(float)\$xSteps))*(\$j/(float)\$ySteps));
float \$w3 = ((1-(\$i/(float)\$xSteps))*(1-(\$j/(float)\$ySteps)));

And all credit should go to Jooja for that.

CGTalk Moderation
01-13-2011, 11:41 AM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.