A-A+

Maya MEL 教程之 mel 打造螺旋曲线

2017-06-09 互动内容
一、Maya MEL 教程之 mel 打造螺旋曲线
了解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 ;”而我们创建螺旋曲线的思路也正基于此。

Maya MEL 教程之 mel 打造螺旋曲线
  首先看代码:string $command="curve -d 3";

for($i=1;$i<=100;$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命令是求函数返回值,也就是将我们的程序计算结果输出。这一步很重要,如果没有这一步,用户可能看不到你所创建的曲线。

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

Maya MEL 教程之 mel 打造螺旋曲线
为方便大家以后的建模,现附上经过修改后的第三方插件,源代码:

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<=($precision*$radius1*2);$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<=($precision*$height);$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 1height;floatSliderGrp -field true-min 0-max 10-fmx 1000000-label "Turns"-value 1turns;floatSliderGrp -field true-min 0-max 10-fmx 100-label "Radius 1"-value 1r1;floatSliderGrp -field true-min 0-max 10-fmx 100-label "Radius 2"-value 1r2;intSliderGrp -field true-min 5-max 20-fmx 1000-label "Precision"-value 10prec;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回车,即可得到下图“创建螺旋曲线”窗口。

null


二、Maya MEL 教程之 mel 打造螺旋曲线 之:山山讲堂 Maya粒子教程之绚丽烟花

  Maya为什么会被那么多的工作者所青睐?Maya为什么会有那么多的忠实粉丝?Maya的精髓是什么?答案只有一点:动力学和角色动画。是强大的特效功能和强大的角色动画功把Maya推入荣誉的殿堂。今天我们就通过Maya的粒子系统以及结合MEL语言,来了解Maya动力学的强大功能吧。

  我们先来看一下最终效果:

  

  Alt+B 切换屏幕的颜色为黑色,模仿黑夜。

  将Maya切换到“Dynamics”模块。选择“Particle”>“Particle Tool”工具创建粒子。在这里我使用的是网格创建粒子的方法。

  
山山讲堂 Maya粒子教程之绚丽烟花

  进入到Particleshape1节点下,修改Maya的生命参数。

  
山山讲堂 Maya粒子教程之绚丽烟花

  在Position属性中单击鼠标右键,选择“Create Expression”,在打开“Expression Editor”的对话框中输入particleShape1.position=sphrand(0.1);

  
山山讲堂 Maya粒子教程之绚丽烟花 山山讲堂 Maya粒子教程之绚丽烟花

  在Velocity属性中单击鼠标右键,选择“Runtime Expression After Dynamics”,在打开的“Expression Editor”对话框中输入if(frame<=38)  particleShape1.velocity=<<0,10*(1/(tan(time))),0>>;  else if(frame>38&&frame<=43)  particleShape1.velocity=sphrand(5);

  
山山讲堂 Maya粒子教程之绚丽烟花

  用户调整时间轴为120针左右,播放测试。

  
山山讲堂 Maya粒子教程之绚丽烟花

  这时我们可以发现,礼花的整体效果已经能够体现了,但是还存在一些小问题,我们来继续调整。

  添加一个重力场,放置到合适高度,造成礼花下垂的效果。

  
山山讲堂 Maya粒子教程之绚丽烟花 山山讲堂 Maya粒子教程之绚丽烟花

  为了模拟礼花的团簇感觉,修改粒子的表现形式为“Multistreak”,并调整其托尾长度为5。

  
山山讲堂 Maya粒子教程之绚丽烟花 山山讲堂 Maya粒子教程之绚丽烟花

  单击“color”属性,添加每粒子属性。

  
山山讲堂 Maya粒子教程之绚丽烟花 山山讲堂 Maya粒子教程之绚丽烟花

  这时我们会在“Per Particle(Array)Attributes”选项卡下多出一个“RGB PP”属性。

  
山山讲堂 Maya粒子教程之绚丽烟花

  在“RGB PP”属性上单击鼠标右键,单击“Creat Ramp”。

  这时我们的RGB PP属性上会多出一些东西,不用理会,再单击鼠标右键,选择“Edit Ramp”,我们打开Ramp节点编辑界面,用户根据测试效果调整颜色就OK了。

  
山山讲堂 Maya粒子教程之绚丽烟花 山山讲堂 Maya粒子教程之绚丽烟花
  现在,我们已经完成了一个五颜六色的礼花效果制作了。用户只要多复制几个,就可以形成绚丽而缤纷的夜景了。说明:我在这里将礼花调整为彩色,用户也可以模仿文章开头的那种效果调整颜色为单一颜色。

三、Maya MEL 教程之 mel 打造螺旋曲线 之:山山讲堂 Maya建模教程之电话建模
本是想通过这篇教程介绍另外一种建模方法——鼎鼎大名的细分建模(Subdiv),但在录制过程中,由于惯性思维的影响,还是采用了多边形建模,不能不说是一个遗憾。为了弥补过失,我将在下一篇飞船建模的教程中与大家详细分享细分建模技术。

  先来看一下最终的效果:

  

山山讲堂 Maya建模教程之电话建模
  创建一个Cube,按照下图参数进行调整。

  

山山讲堂 Maya建模教程之电话建模

山山讲堂 Maya建模教程之电话建模 山山讲堂 Maya建模教程之电话建模
  进入点级别,调整点的位置。

  

山山讲堂 Maya建模教程之电话建模
  使用“Insert Edge Loop Tool”工具添加环线。

  技巧:在使用Insert Edge Loop Tool工具的时候,为了一次性添加,我们可以打开改工具的设置选项,具体设置如下:  

山山讲堂 Maya建模教程之电话建模
  使用Extrude命令进行三次挤压,效果如下图所示。

  

山山讲堂 Maya建模教程之电话建模
  添加环线,保留形状。

  

山山讲堂 Maya建模教程之电话建模
  使用Extrude命令进行挤压。

  

山山讲堂 Maya建模教程之电话建模
  添加环线,保留形状。

  

山山讲堂 Maya建模教程之电话建模
  重复上面的方法,制作出下图所示部分。

  

山山讲堂 Maya建模教程之电话建模
  使用Extrude挤压,并调整点的位置。

  

山山讲堂 Maya建模教程之电话建模
  继续挤压。

  

山山讲堂 Maya建模教程之电话建模
  使用“split polygon tool“添加线,保留形状。

  

山山讲堂 Maya建模教程之电话建模 山山讲堂 Maya建模教程之电话建模
  挤压面,记住一定要关闭“keep faces together”选项。  
山山讲堂 Maya建模教程之电话建模 山山讲堂 Maya建模教程之电话建模
  添加环线,保留形状。

  

山山讲堂 Maya建模教程之电话建模 山山讲堂 Maya建模教程之电话建模
  细分。

  

山山讲堂 Maya建模教程之电话建模
下面我们来制作话筒。

  创建Cube,具体参数如下图所示。

  

山山讲堂 Maya建模教程之电话建模

山山讲堂 Maya建模教程之电话建模 山山讲堂 Maya建模教程之电话建模
  F8进入点级别,调整点的位置。

  

山山讲堂 Maya建模教程之电话建模
  添加环线,保留形状。

  

山山讲堂 Maya建模教程之电话建模
  使用Extrude命令进行挤压。

  

山山讲堂 Maya建模教程之电话建模 山山讲堂 Maya建模教程之电话建模 山山讲堂 Maya建模教程之电话建模 山山讲堂 Maya建模教程之电话建模
  重复上面的步骤,挤压出话筒部分。

  

山山讲堂 Maya建模教程之电话建模
  细分。

  

山山讲堂 Maya建模教程之电话建模
  制作电话线。这一部分比较难,但也比较简单。为什么这样说呢?如果你曾读过我前面的螺旋曲线教程的话,这里你只要写一个简单的MEL语言,就可实现我们想要的效果,如下图所示。

  

山山讲堂 Maya建模教程之电话建模
  然后用户使用Surfaces下的Extrude命令就可实现电话线的制作。

  

山山讲堂 Maya建模教程之电话建模
  今天换一个制作方法,我给大家提供专门制作电话线的脚本,这样更加方便快捷。

  global proc phoneCord1( string $curv, float $numLoops )

  {

   int $numCvs, $i;

   float $p, $min, $max, $angle, $uoff, $voff;

   string $exp_str, $crv, $p_on_c;

   int $cvsPerLoop = 4;   // We base the number of cvs on

   $numCvs = (int) ($numLoops+.5) * $cvsPerLoop;

   $crv = curve( "-d", 3, "-p", 0, 0, 0, "-k", 0, "-k", 0, "-k", 0 );

   $min = getAttr( $curv + ".min" );

   $max = getAttr( $curv + ".max" );

   // create a curve with the required number of cvs

   for( $i = 1; $i <= $numCvs; $i++ )

   {

   curve -a -p ((float)$i) 0 0 $crv ;

   }     // Add a loopOffset attribute to the spiral curve   addAttr -sn loff -ln loopOffset -dv 1.0 -min 0 -max 10 $crv;

   setAttr -keyable on ($crv + ".loopOffset");   for( $i = 0; $i <= $numCvs; $i++ )

   {

   $p = (float)$i/$numCvs;

   $angle = $p * $numLoops * 6.28;

   $uoff = -sin( $angle );

   $voff = cos( $angle );   // we set the offset to zero for the start and end cvs

   if( $i == 0    $i == $numCvs )

   {

   $uoff = 0;

   $voff = 0;

   }

   $p = $min + ($max -$min) * $p;

   // create a pointOnCurve node on the source curve

   $p_on_c = pointOnCurve( "-ch", 1, "-parameter", $p, $curv );   // Create an expression to position the spiral

   // cvs relative to the source curve using the

   // point, normal and tangent from the pointOnCurve node

   // A cross product is performed to give a vector perpendicular

   // to the normal and tangent. The 2D rotation is then mapped to

   // this vector and the normal.

   expression -s ("$u = " + $uoff + " * " + $crv + ".loff;\n"

   + "$v = " + $voff + " * " + $crv + ".loff;\n"

   + "$nx = " + $p_on_c + ".nnx;\n"

   + "$ny = " + $p_on_c + ".nny;\n"

   + "$nz = " + $p_on_c + ".nnz;\n"

   + "$tx = " + $p_on_c + ".ntx;\n"

   + "$ty = " + $p_on_c + ".nty;\n"

   + "$tz = " + $p_on_c + ".ntz;\n"

   + $crv + ".cp[" + $i + "].xv = " + $p_on_c

   + ".px + ($ny * $tz - $ty * $nz) * $u + $nx * $v;\n"

   + $crv + ".cp[" + $i + "].yv = " + $p_on_c

   + ".py + ($tx * $nz - $nx * $tz) * $u + $ny * $v;\n"

   + $crv + ".cp[" + $i + "].zv = " + $p_on_c

   + ".pz + ($nx * $ty - $tx * $ny) * $u + $nz * $v;\n");

   }    }  global proc xyphoneCord()

  {

  if ( `window -exists phoneCord` )

  deleteUI xyphoneCord;  window

  -maximizeButton false

  -resizeToFitChildren true

  -title "phoneCord"

  -iconName "phoneCord" xyphoneCord;

  columnLayout -columnAttach "both" 5 -rowSpacing 2 -columnWidth 210;

   intFieldGrp -label "number" -v1 50 -cal 1 "left" phoneCordnumber;

   button -label "select a curve,make cord" -c xymakecord;

  showWindow xyphoneCord;

  }

  global proc xymakecord()

  {

   int $cordnum = `intFieldGrp -q -v1 phoneCordnumber`;   string $curveselect[];

   $curveselect=`ls -sl`;

   phoneCord1 $curveselect[0] $cordnum;

   xyQuickTube;

  createAndAssignShader blinn "";  }  proc string tube( string $cs ) // (curve shape)

  {

  string $t[];  

  if (objExists($cs) && (nodeType($cs)=="nurbsCurve"))

  {

  string$c=`createNode makeNurbCircle -n "baseCircle1"`;

  string$s=`createNode subCurve -n "profileRange1"`;

  string$e=`createNode extrude`;

  string$r=`createNode nurbsSurface -n "tube1"`;

  

  setAttr -e -k 0 ($c+".normal");

  setAttr -e -k 0 ($c+".normalX");

  setAttr -e -k 0 ($c+".normalY");

  setAttr -e -k 0 ($c+".normalZ");

  setAttr -e -k 0 ($c+".centerZ");

   setAttr ($c+".radius") 0.1;

  setAttr ($s+".minValue") 0.0;

  setAttr ($s+".maxValue") 1.0;

  setAttr ($s+".relative") 1;  

  setAttr ($e+".extrudeType") 2;

  setAttr ($e+".useComponentPivot") 1;

  setAttr ($e+".useProfileNormal") 1;

  setAttr ($e+".fixedPath") 1;  setAttr -e -k 0 ($e+".directionX");

  setAttr -e -k 0 ($e+".directionY");

  setAttr -e -k 0 ($e+".directionZ");

  setAttr -e -k 0 ($e+".useComponentPivot");

  setAttr -e -k 0 ($e+".useProfileNormal");

  setAttr -e -k 0 ($e+".fixedPath");

  setAttr -e -k 0 ($e+".rotation");

  setAttr -e -k 0 ($e+".scale");

  setAttr -e -k 0 ($e+".length");

  

  connectAttr ($c+".outputCurve") ($e+".profile");

  connectAttr ($cs+".worldSpace") ($s+".inputCurve");

  connectAttr ($s+".outputCurve") ($e+".path");

  connectAttr ($e+".outputSurface") ($r+".create");

  $t=`listRelatives -pa -p $r`;

  }

  return($t[0]);

  }

  //

  // main procedure

  //

  //

  global proc xyQuickTube()

  {

  string $sl[]=`ls -sl`, $s, $r[];

  for($s in $sl)

  {

  string $sh[]=`listRelatives -pa -s $s`;

  if ($sh[0]!="") $r[size($r)]=tube($sh[0]);

  }

  select -r -ne $r;

  }

  用户执行该段代码后,会弹出窗口。

  

山山讲堂 Maya建模教程之电话建模
  用户选择一段曲线执行该命令,即可生成电话线。

  

山山讲堂 Maya建模教程之电话建模
  将所有部件进行装配。

  

山山讲堂 Maya建模教程之电话建模
标签:螺旋   曲线   打造   教程   Maya