Maya MEL 教程之 mel 打造螺旋曲线-Maya
了解Maya的人都知道Maya本身不能够创建螺旋曲线,这给我们在建模电话线、弹簧等具有螺旋结构的模型时带来了很多不便。那么怎样解决这个问题呢?就目前来看,主流的解决方法是采用外部插件,但由于需要到国外网站上下载,普通中国用户很难发掘到;而通过手动创建螺旋曲线的方法不仅方法笨拙,效率低下,而且在很多时候也很难满足我们的工作要求。今天小编就通过一个简单MEL程序来达到我们的要求,也希望借此抛砖引玉。
熟悉Maya的人都知道,Maya的任何一条命令都是一个MEL口令,例如我们在Maya中创建一条样条曲线,在Maya的脚本编辑器中就会显示这样的一条MEL口令:“curve -d 3 -p -6.121508 0 6.545092 -p -6.084318 0 -1.667924 -p -1.898864 0 6.298442 -p 0.172602 0 -1.310417 -p 2.51464 0 6.576429 -k 0 -k 0 -k 0 -k 1 -k 2 -k 2 -k 2 ;”而我们创建螺旋曲线的思路也正基于此。

首先看代码:
string $command="curve -d 3";
for($i=1;$i
{
float $x=5*sin($i);
float $z=5*cos($i);
float $y=$i;
$command+=" -p "+$x+" "+$y+" "+$z;
};
eval $command;
解释:
第一行 —— Maya的mel语言规定,变量前必须添加符号$。curve是mel命令,即创建曲线;-d定义曲线精度为3;该行的含义就是定义字符串变量“$command”。
第二行 —— 执行for循环语句。定义整数$i,自增100次,其实就是表示有100个CV点。
第四行 —— 定义实数$x,并将5*sin($i)赋值给$x。而第五行、第六行的语法与第四行相同。在本例中,第四行、第五行、第六行是程序关键,其实这三行就是螺旋线的数学方程式。
第七行 —— 将字符串合并,也就是获得一个创建曲线的完整表达方式,类似于:curve -d 3 -p -6.121508 0 6.545092 -p -6.084318 0 -1.667924 -p -1.898864 0 6.298442...
第九行 —— eval命令是求函数返回值,也就是将我们的程序计算结果输出。这一步很重要,如果没有这一步,用户可能看不到你所创建的曲线。

总结:
该mel程序的扩张性很强,用户可通过修改螺旋线的参数,进而获得其他形式的曲线。例如,当将螺旋线的半径5修改为$i,则可以获得圆锥螺旋线。

为方便大家以后的建模,现附上经过修改后的第三方插件,源代码:
global proc int helix_startSequence()
{float $h, $t, $r1, $r2, $a, $k, $t0;
int $prec, $encs, $encr, $encp, $helpVar;
string $nm, $NM;
$nm = `textField -q -text name`;
$NM = $nm + helix_checkName($nm);
$h = `floatSliderGrp -q -value height`;
$t = `floatSliderGrp -q -value turns`;
$r1 = `floatSliderGrp -q -value r1`;
$r2 = `floatSliderGrp -q -value r2`;
$prec = `intSliderGrp -q -value prec`;
$helpVar=`radioButtonGrp -q -sl radioButtons`;
if(`textField -q -en A`)
{$a=`textField -q -text A`;
$k=`textField -q -text K`;
$t0=`textField -q -text T`;
}
else
{ $a = 1.0;
$k = 0.0;
$t0 = 90.0;
}
if($helpVar==1) {$encs = 1; $encr = 0; $encp = 0;}
if($helpVar==2) {$encs = 0; $encr = 1; $encp = 0;}
if($helpVar==3) {$encs = 0; $encr = 0; $encp = 1;}
if($helpVar==4) helix_drawSphere($NM, $t, $r1, $prec);
if($helpVar!=4) helix_drawHelix($NM, $h, $t, $r1, $r2, $prec, $a, $k, $t0, $encs, $encr, $encp);
return 0;
}
global proc int helix_checkName(string $NAME)
{int $number=0,$ok,$k;
string $NAM;
for($ok=0;$ok==0;$k++)
{$number++;
$NAM=$NAME+$number;
if(!`objExists $NAM`) $ok=1;
}
return $number;
}
global proc int helix_drawSphere(string $name, float $turns, float $radius1, int $precision)
{float $y, $X, $Y, $Z, $i, $negRadius1;
$negRadius1=-$radius1;
for($i=0;$i
{$y = $i / $precision;
$X = sqrt(($radius1*$radius1)-($y-$radius1)*($y-$radius1))*cos(($y*$turns*2*3.14159265)/($radius1*2));
$Y = $y;
$Z = sqrt(($radius1*$radius1)-($y-$radius1)*($y-$radius1))*sin(($y*$turns*2*3.14159265)/($radius1*2));
if(!`objExists $name`)
{curve -d 3 -p 0 0 0;
rename `ls -sl` $name;
}
else curve -a -p $X $Y $Z $name;
}
CenterPivot;
move 0 $negRadius1 0;
return 0;
}
global proc int helix_drawHelix(string $name, float $height, float $turns, float $radius1, float $radius2, int $precision, float $Amp, float $tms, float $ngl, int $ENCS, int $ENCR, int $ENCP)
{float $t1, $t2, $t3, $t0;
float $y, $X, $Y, $Z, $i;
for($i=0;$i
{float $tempy;
$t0=$Amp*sin(($tms*$y/$height)+3.14159265*($ngl/180));
$t1=($y/$height)*$ENCS;
$t2=(sqrt($y/$height))*$ENCR;
$t3=($y*$y/($height*$height))*$ENCP;
$y = $i / $precision;
$X = $t0*($radius1-($radius1-$radius2)*($t1+$t2+$t3))*cos(($y*$turns*2*3.14159265)/$height);
$Y = $y;
$Z = $t0*($radius1-($radius1-$radius2)*($t1+$t2+$t3))*sin(($y*$turns*2*3.14159265)/$height);
if(!`objExists $name`)
{curve -d 3 -p $radius1 0 0;
rename `ls -sl` $name;
}
else curve -a -p $X $Y $Z $name;
}
return 0;
}
global proc int helix_changeState(int $statNr)
{if($statNr==1)
{floatSliderGrp -e -en 0 r2;
floatSliderGrp -e -en 0 height;
checkBox -e -en 0 box;
textField -e -en 0 A;
textField -e -en 0 K;
textField -e -en 0 T;
}
if($statNr==2)
{floatSliderGrp -e -en 1 r2;
floatSliderGrp -e -en 1 height;
checkBox -e -en 1 box;
if(`checkBox -q -value box`)
{textField -e -en 1 A;
textField -e -en 1 K;
textField -e -en 1 T;
}
}
if($statNr==0)
{if(`textField -q -en A`==0)
{textField -e -en 1 A;
textField -e -en 1 K;
textField -e -en 1 T;
}
else
{textField -e -en 0 A;
textField -e -en 0 K;
textField -e -en 0 T;
}
}
return 0;
}
global proc int helix_exitWindow()
{deleteUI Helix;
return 0;
}
global proc helix()
{
if(`window -q -exists Helix`) deleteUI Helix;
window -w 200 -h 400 -title "Helix properties" Helix;
scrollLayout sl1;
columnLayout;
frameLayout -cll true -label "Helix properties";
columnLayout;
rowColumnLayout -numberOfColumns 2;
text -label "Name";
textField -text "Helix" name;
setParent ..;
rowColumnLayout -numberOfRows 5;
floatSliderGrp -field true
-min 0.0001
-max 10
-fmx 1000
-label "Height"
-value 1
height;
floatSliderGrp -field true
-min 0
-max 10
-fmx 1000000
-label "Turns"
-value 1
turns;
floatSliderGrp -field true
-min 0
-max 10
-fmx 100
-label "Radius 1"
-value 1
r1;
floatSliderGrp -field true
-min 0
-max 10
-fmx 100
-label "Radius 2"
-value 1
r2;
intSliderGrp -field true
-min 5
-max 20
-fmx 1000
-label "Precision"
-value 10
prec;
setParent ..;
setParent ..;
setParent ..;
frameLayout -cll true -label "Shape properties";
columnLayout;
rowColumnLayout -numberOfRows 5;
radioButtonGrp -numberOfRadioButtons 4
-labelArray4 "Straight" "Parabolic1" "Parabolic2" "Sphere"
-sl 1
-on4 "helix_changeState 1"
-of4 "helix_changeState 2"
radioButtons;
checkBox -label "Combine with Asin(Kx+T)" -cc "helix_changeState 0" box;
setParent ..;
rowColumnLayout -numberOfColumns 2;
text -label "A";
textField -text "1" -en 0 A;
text -label "K";
textField -text "1" -en 0 K;
text -label "T in degrees";
textField -text "90" -en 0 T;
setParent ..;
setParent ..;
setParent ..;
rowColumnLayout -numberOfColumns 2;
button -label "Cancel" -command "helix_exitWindow()";
button -label "Create" -command "helix_startSequence()";
showWindow Helix;
}
使用方法:
首先将该代码拷贝到你的脚本编辑器中,然后CTRL+回车键执行,最后在MEL命令栏(Maya窗口最下方)中输入helix回车,即可得到下图“创建螺旋曲线”窗口。
