加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

MEL中一些数学运算命令知识

(2011-01-22 14:20:23)
标签:

杂谈

mel语言是maya自己内部的一套编程语言,mel是maya的灵魂,是maya执行命令的语言。稍有编程基础的话,可以很容易掌握它。我们可以看到除了maya的插件(maya内部很多组件也都是以插件形式存在的)以外,所有的操作都可以在script editor窗口中有相应的mel语言与之对应。例如:创建一个常规的polygon球体,打开windows-->General Editors-->Script Editor,可以看到:polySphere -r -sx 20 -sy 20 -ax -tx -ch 1;;这句话的意思是创建一个polygon球体(polySphere),其半径为1(-r 1),x、y轴向的分段皆为20(-sx 20 -sy 20),轴向为Y轴向上(-ax 0),显示方式为有锯齿贴图(-tx 2),并带有历史纪录(-ch 1)。参见help中的polySphere词条。
*表达式的作用:
1,使属性与时间建立关系,来产生动画效果。
2,建立属性与属性的联系,来达到用一个属性控制另一个属性的目的。
/////////////////////////////////
一:MAYA中的预定义变量(时间)
1,"time"是一个变量,单位“秒”。
2,"frame"是一个变量,单位“贞”。
(*注意*属性的名称一定要写完整,并在写完后加终止符“;”)
例如:nurbsSphere1.translateX time;
(*注意*属性名称是分大小写的,"aa Aa AA "是三个完全不同的名称)
(其中“=”相当于赋值操作符,顺序是自右向左先计算等号右侧,再把       结果赋给左侧。)
*数学运算符;
   “+”(加);“-”(减);“*”(乘);“/”(除);“%”(取于    ,相当于一个数被另一个数整除后的余数)
二:MAYA中的自定义变量
   作用:用来存储表达式中用到的临时结果。
   类型:1;浮点型变量:(就是带有小数点的变量)
          声明符为“float”;
          例如:float $aa 3.14159;
          (*注意* a,所有变量名称前必须加“$”。
                  b,变量的名称必须以英文字母开头。
                  c,变量名称中不准许出现特殊符号,例如                                “!,@,#,%,^,&,*"但可以出现下划线和数字”float                      $aa_1"。
                  d, 变量名称严格区分大小写,例如:“$aa,$Aa”是两                     个完全不同的变量。)
         2;整数型变量;
           声明符为“int”;
           例如:int $bb 10;
         3;字符串变量;
           声明符为“string";
           例如:string $cc "maya7.0";
         4;矢量变量;
           声明符为“vector ”;
           例如:vector $dd <<3.3,4,-5.5>>;
三;MAYA中的语句和运算符
   1,条件语句
     if (条件)//(“如果”的意思)
     {
      语句1;
      语句2;
      }
     例如;if (time 3)
     (*注意*条件语句后不能加“;”)
      也可以同“else”(当“否则”讲)配合使用;
     例如;
         if (time 3)
         ball.tx -6;
         else if (time >= && time <= 6)
         ball.tx 0;
         else
         ball.tx 6;
         或者不嵌套写,并列写也可以。
         if (time 3)
         ball.tx -6;
         if (time >= && time <= 6)
         ball.tx 0;
         if (time 6)
         ball.tx 6;
        (*注意*多重并列时条件不能冲突,不可同时满足两个以上的条件          。)
    2,关系运算符
      “〈”(小于)//“〉”(大于)//“〈=”(小于等于)//“〉=”       (大于等于)//“==”(等于)//“!=”(不等于)
        (*注意*如果条件后要用等号,一定要用双等号“==”)
    3,逻辑运算符
       “&&”(并且)(相乘的关系,必须两个条件同时成立)
       “||”(或者)(相加的关系,有一个条件成立即可)
       “!”(非)
    4,快捷操作符
       “+=”“-=”“*=”“/=”“%=”“++”“--”
       (以上均是在自身的基础上进行)
     *“print”(“打印”把变量的数值显示在屏幕上)*
四;MAYA中的函数
    1,算术函数
      a;“abs( )”(绝对值函数)
        例如;abs(5)     5
              abs(-5.5) 5.5
              abs(0)     0
      b;“ceil( )” (返回比括号中数大的最小整数)
        例如;ceil(4.3) 5
              ceil(-2.3) -2
      c;“floor( )”(返回比括号中数小的最大整数)
        例如;floor(4.3) 4
              floor(-5.6) -6
      d;“trunc( )”(取得括号中数的整数位)
        例如;trunc(10.39) 10
              trunc(-3.14) -3
      e;“min(x,y)”(取得括号中两数比较后较小的数)
        例如;float $a 6.3;
              float $b 5.6;
              float $c 4.3;
              float $min min($a,$b);
              float $min min($min,$c);
      f;“max(x,y)”(取得括号中两数比较后较大的数)
        例如;max(2.1,3.5) 3.5
      g;“sign()”(返回括号中的符号,正数返“1”,负数返“-1          ”,零则返回“0”)
        例如;sign(5) 1
              sign(-5) -1
              sign(0) 0
      h;“clamp(min,max,parameter)”(求范围,当parameter小于min         时则返回min,当大于 max时则返回max,在min和max之间时则反回         其自身)
        例如;clamp(0,1,time);(只取time“0-1”的部分)
     2,指数函数
       a;“exp( )”(求衰减系数“e”的多少次方)(e 2.718);
         例如;exp(time);(基于时间递增)
       b;“pow(x,y)”(求x的y次方)
         例如;pow(2,3) 8
               pow(8,1.0/3) 2
       c;“sqrt( )”(专用开平方)
         例如;sqrt(4) 2
       d;“log(x)”(求x是e的多少次幂)
         例如;log(1)      0
               log(2.718) 1
       e;“log10(x)”(求x是10的多少次幂)
         例如;log(100)    2
               log(1)      0
               log(1000)   3
       f;“hypot(x,y) (勾股定理)
         例如;hypot(3,4)   5
      3,随机函数
        a;”noise( )”(噪音)
          例如;noise(time)
                noise(frame)
        b;“dnoise( (噪音,对矢量进行操作)
          例如;dnoise(<<2,3,4>>)
        c;“rand( )”(随机函数的一种,针对浮点类型)
          例如;rand(5) 在0到5之间随机
                rand(2,4) 在2到4之间随机
        d;“seed )”(固定随机函数)
          例如;seed(1) 1
        e;“sphrand )”(针对矢量的球型随机)
          例如;sphrand(5)
                sphrand(<<5,1,5>>)
      4,三角函数
        a;“sin )”(正弦函数)
          例如;sin(1) (表示1弧度的正弦值)1弧度=180/3.14度
        b;“cos )”(余弦函数)
          例如;cos(1) (表示1弧度的余弦值)
      5,转换函数
        a;“deg_to_rad”(将角度转为弧度)
          例如;deg_to_rad(180) 3.14
        b;“ hsv_to_rgb”(颜色转换模式)
          例如;hsv_to_rgb(<<360,1,1>>) <<1,0,0>>
      6,曲线函数
        ;“linstep(min,max,parameter)”(线性递增函数,返回值永远是从0到1)
           例如;linstep(3,6,time)
        b;“hermite( )”(自定义曲线函数,且返回结果也为矢量,用法较为复杂)
       7,矢量函数
           a;“mag )”(求矢量大小,求得的结果是一个浮点数)
          例如; mag(<<3,4,5>> <<1,2,3>>)   3.464102
           b;"angle ()" (求得两矢量之间的加角,单位永远是弧度,永远取小的角度,永远取正数)
 
MEL语法格式规范

MEL语法!
每个变量就像个储存箱。箱子有名字,以方便你或Maya找到它。箱里收藏(或获分配)的数值有以下几种类型:
整数,例如
int $myint 314
浮点数,例如
float $myfloat 7.6122
矢量(能用来代表位置或颜色),例如
vector $myvec <<1.2, 7.3, 22.38>>
字串,例如
string $mystr "This is string"
注意矢量值和字串值的写法: 矢量里的三个数字用 << 和 >> 包着,而字串里的字符则用两个 包着。你若要调用矢量里头的分量,就用 $myvec.x,$myvec.y 和 $myvec.z,比如
$myfloat $myvec.x
变量名字前面必须加个$。你只能用 至 Z,a 至 z,0 至 9,和 这几个字母来命名,其它(包括空格)一概不能用。名字的第一个字母不可以用数目字。字母的大小楷对Mel来说都有别。比如$Myvar,$myVar 和$myvaR是不同的名字,所代表的也是不同的变量。
变量的类型必须和它所收藏的数值类型匹配。比如
float $myfloat "This is string"
是不能成立的。那倒是相当明显,那么
float $myfloat "7.6122"
又如何?
要创造一个无值变量,只需输入(比如)int $newvar。 然后用 $newvar 23 赋予它一个值。
所有变量一经设立就无法被删除或改变类型,除非你跳出Maya。以$newvar为例,这名字会一直代表一个整数变量;你不能改用它来存放其它类型的数据。
当你储存场景时,你创造的变量不会自动跟着场景被存起来。但迟点我会教你一个能在场景里保存变量的技巧。
你也能同时创造几个变量:
int $newvar1, $newvar2, $newvar3
你不能同时赋予他们不同的数值,但如果数值是同等的话你倒可以写
$newvar1 $newvar2 $newvar3 5

数组
当你创造一个变量时,你可以把它设为一个组:
float $myfloat[4]
方括号里的4说明这数组能收藏四个浮点值。你可以用以下句子把数值分配给它:
$myfloat {3.4, 22.1, 0.53, 87.33}
或者
$myfloat[0] 3.4; $myvar[1] 22.1; $myvar[2] 0.53; $myvar[3] 87.33;
注意那索引是从0开始算的,还有我们用分号把几个句子分开。
其它类型的变量也能组化:
string $mystr[3] {"string1", "string2", "string3"};
vector $myvec[2] {<<2.1, 3.3, 10.2>>, <<12.5, 23.6, 78.8>>};
其实组员的数量是不定的。比如上面的$myfloat虽说能储藏四个组员,但若你写
$myfloat[4] 3.11
的话,它会立刻增多一个位子来收留这新组员。这种数组在英文叫做dynamic array,则是说它的组位数量有伸缩性。根据这特性,你可以用 float $myfloat[] 设立数组,然后靠分配数值自动增加它里头的位子数量。
Size这指令能给你报一个数组内有多少个组员,而clear则能帮你把它们全清除掉:
size $myfloat; clear $myfloat;
数组的主要用意是给你方便地储存概念上相同但形体上分很多份的数据。比如你想把你5个朋友的电话号码纪录下来,用
string $name[5] {"John", "Mary", "Peter", "Paul", "Walter"};
int $phone[5] {9711234, 3967541, 8809472, 7825162, 5091208};
会比
string $name1, $name2, $name3, $name4, $name5;
int $phone1, $phone2, $phone3, $phone4, $phone5;
$name1 "John"; $name2 "Mary"; $name3 "Peter"; $name4 "Paul"; $name5 "Walter";
$phone1 9711234; $phone2 3967541; $phone3 8809472; $phone4 7825162; $phone5 5091208;
来得好。不只是因为前者可以打少点字,更重要的是因为它用一个简单数字给两组不同类型的数据贴标,让你过后能方便地找到你要的资料:
int $indx 2;
print $name[$indx]; print "; print $phone[$indx];
$indx 4;
print $name[$indx]; print "; print $phone[$indx];
等你学到循环计算法时,这方便性会更明显。
矩阵
除了int,float,vector和string之外,还有一种数据类叫matrix(中称矩阵)的。你可以当它作浮点数组的数组来用。它的设立用
matrix $mymatrix[2][3]
值的分配用
$mymatrix <<3.49, 1.12, 4.47;
                1.15, 1.21, 0.76>>

$mymatrix[0][0] 3.49; $mymatrix[0][1] 1.12; $mymatrix[0][2] 4.47;
$mymatrix[1][0] 1.15; $mymatrix[1][1] 1.21; $mymatrix[1][2] 0.76;
矩阵有一点跟普通浮点数组不同的是你设立它时必须说明它有多少个组员,而且这数量过后不能改变。这种组类在英文叫做static array。以$mymatrix为例,你不能执行 $mymatrix[2][0] 65.33,因为 [2] 超过了 $mymatrix 最高行数([1])。
基本算法
+(加) -(减) *(乘) /(除)你应该很熟悉吧?
float $opresult 1
噢,等一等,四除二后乘三再加一,不是等于2.5吗?怎么报回的数字是2呢?因为这表达式里全是整数,所以Maya把计算出来的小数点删除了。再试试看
$opresult 3.0 2.0 4.0 1.0
+有个特别功能,就是可以用来连接字串:
string $str1 "I am ";
string $str2 "a good ";
string $str3 $str1 $str2 "MEL programmer.";
还有一个较少见的运算符,%,是给你算余数用的,比如
float $remain 5
会得2,因为那正是5除7后剩余的数字(7 2)。 猜猜 5.9999%6.0 和 10.0001%10.0 会得什么数字?
如果操作数是矢量的话,这些算法是针对每个分量算的,比如
vector $vec1 <<1, 2, 3>>;
vector $vec2 <<4, 5, 6>>;
vector $vec3 $vec2 $vec1;
$vec3就会获得<<0, 1, 0>>。 注: 在矢量计算里叫点乘。还有一种矢量乘法叫叉乘,用 代表。
拒阵互相加减时,它们的行栏数必须是相等的。互乘时,左边矩阵的栏数必须等于右边的行数。
matrix $Va[1][4] <<2, 0, 0, 2>>;
matrix $Vb[1][4] <<6, 3, 7, 5>>;
matrix $Vc[1][4] $Va $Vb; --> 得 <<8, 3, 7, 7>>
matrix $Vd[1][4] $Vc $Vd; --> 得 <<-4, -3, -7, -3>>
matrix $Ve[2][4] <<4, 1, 1, 2; 3, 4, 5, 8>>;
matrix $Vf[4][3] <<7, 6, 0; 7, 5, 4,; 2, 1, 6; 2, 0, 2>>;
matrix $Vg[2][3] $Ve $Vf; --> 得 <<41, 30, 14; 75, 43, 62>>
matrix $Vh[2][3] $Vg; --> 得 <<82, 60, 28; 150, 86, 124>>
和 不能用于两个拒阵之间,但能用于一个拒阵和一个标量(整数或浮点数,英文统称scalar)之间。那标量必须处于右边:
matrix $testmat1[1][4] <<4, 9, 5, 2>> 3; --> 得 <<1, 0, 2, 2>>
matrix $testmat2[1][4] <<1, 2, 8, 4>> 2; --> 得 <<0.5, 1, 4, 2>>

改值分配缩写
$var $var 17 可以缩写成 $var += 17。其他算号也能这么写。若你想把变量值增加或削减一的话,还有更简短的写法: $var++,++$var,$var-- 或 --$var;那双算号若放在变量名前面的话,就先改值,后做其它分配工作;放后面的话则相反。
float $eel 32.3;
float $crab $eel++; --> $crab得32.3,$eel得33.3
$crab $eel--; --> $crab得33.3,$eel得32.3
$crab --$eel; --> $crab得31.3,$eel得31.3
$crab ++$eel; --> $crab得32.3,$eel得32.3

测验句子
下列句子若测验出是对的话,就会给回1,否则给回0。
$var1 $var2; --> $var1小于$var2 ?
$var1 $var2 --> $var1大于$var2 ?
$var1 == $var2 --> $var1等于$var2 ?
$var1 != $var2 --> $var1不等于$var2 ?
$var1 >= $var2 --> $var1大于或等于$var2 ?
$var1 <= $var2 --> $var1小于或等于$var2 ?
$var1 $var2 || $var1 $var3 --> $var1小于$var2或大于$var3?
$var1 $var2 && $var1 $var3 --> $var1小于$var2而且大于$var3?
!$var1 --> 若$var1代表0就给回1,否则给回0
上面最后那个句子里头的$var1可以用其它较复杂的测验句子代替,如
!($var1 $var2 && $var1 $var3)
注意句子周围的括号。你了解这括号的用意吗?
带条件的值分配
在分配值时,你可以用一个测验条件来选择两个值之中的一个。比如
string $finvar 10 11 "smaller" "larger"
就表示如果10小于11的话(当然是),就把"smaller"分配给$finvar,不然就分配"larger"给它。这语法有一个细节需要注意: 那两个选择值的类最好是匹配的。虽然这好像是很明显,但你试试执行以下句子:
float $mog 3.3
因为8这整数先出现,Maya会把3.3变成3以跟它匹配,然后把这3分配给$mog(测验句子的0代表“错”,1则代表“对”)。
算法的优先次序
以下列表显示所有运算符的优先次序。越高的就越优先受处理。同等级的运算符,在表达式里排在左边的先被处理。
() []
++ --
^
-
<= >=
== !=
&&
||
?:
+= -= *= /=
逻辑运算
若要按照某些条件执行某些指令的话,就用
if( 测验句子 测验出是对的话要执行的句子;
比如
int $newint;
if( $newint 10;
注意这后面只能执行一个句子。若要执行多个句子的话就必须用复合句子:
int $newint1, $newint2;
if( {
    $newint1 10;
    $newint2 20;
}
你也可以制定当测验出错结果时该执行的另一个指令:
if( $newint 10;
else {$newint1 10; $newint2 20;}
你到现在也该留意到MEL对于要隔多少行或空位等写法细节没什么拘束。上面那程序你大可写成
if (1 2)
    $newint 10;
else {
    $newint1 10;
    $newint2 20;
}
可能更易读。
注意: 你在{}里设立的变量一出了括号范围就不见了。比如
$newint1 3;
if (1 2) {$newint1 10;}
执行后$newint1的值还是保持在3。 括号里的$newint1是跟外面的$newint1不同的一个临时变量。
你可以把多个if和else串起来用:
if ($newint1 == 0) {print "Hi"; print "Bobo";}
else if ($newint1 == 1) print "Ho";
else if ($newint1 == 2) print "Hu";
else {print "He"; print "Kaka";}
这类多层测验的句子用一种叫switch的结构来写也许会比较整齐:
switch ($newint1)
{
    case 0: print "Hi";
            print "Bobo";
            break;
    case 1: print "Ho";
            break;
    case 2: print "Hu";
            break;
    default: print "He";
             print "Kaka";
             break;
}

循环运算
MEL基本上有两种循环运算写法:
while( 测验 循环句子;
for( 整个循环前执行的句子; 测验; 每一次循环步骤的善后句子 循环句子;
两种写法的运作原理都是一样的 -- 只要测验的结果是对的话,那循环句子(一个简单句子或复合句子)就会重复执行,直到测验结果是错为止。例子:
int $i 10;
while ($i 0) {
    print $i--;
    print ";
}
int $j;
string $names[100];
for ($j 0; $j 100; $j++) $names[$j] "friend" $j;
在这之前我提到组数和循环计算配合的好处,现在可以看到了吧?若还是看不到的话,试想怎么储存和提询上面那一百个名字。
循环写法里的任何一个部分都可以留空。比如你可以用
$j 0;
for (; $j 10000000; $j++);
使Maya停顿一下。还有,for括号里的前后期句子都可以用多个句子组成:
for( $i 10, $j 100; $i 50; $i++, $j++ {
    print $i; print "; print $j; print "\n";
}
注意个别句子是用逗号分开的。还有后面那个"\n"代表新行。
while有个危险性,就是你会很容易忘记设立一个让它停止运算的机关。比如
$i 0;
while( $i 10 print "Hi"; --> 别执行!
就会永不休止地执行下去。
while有个另一个写法:
do 循环句子; while 测验 )
这写法会执行循环句子至少一次,无论测验结果如何。
for也有另一个专门对组数的用法:
for 变量 in 组数 循环句子;
比如
string $car;
string $cars[3] {"NSX", "Porsche", "Acura"};
for ($car in $cars) print ("I have $car "\n");
在循环句子里,你可以用continue跳过现阶段的计算或用break完全停止循环。
for ($i 1; $i 50; $i++) {
    if ($i == 15) continue;
    if ($i == 25) break;
    print ($i "\n");
}

程序
你可以把一连串句子包装成一个程序,然后如用一个指令一样去执行它。
proc 返回值类 程序名 各种参数类和名 各种句子 }
比如
proc string printword( string $word, int $num )
{
    int $i;
    for( $i 0; $i $num; $i++ print ($word "\n");
    string $outval "Printed $num words.";
    return $outval;
}
注意在外面的返回类必须和程序里的返回值匹配。这程序成立后,你就能用(比如)printword "Myword" 执行它。你也可以用 string $catchval `printword "Myword" 7` 把程序返回的值赋予一个变量。
这类自定程序不随场景储存。
脚本
在没开始这部分教程之前,先在D磁盘创造一个叫myhome的文件夹。然后设立一个叫MAYA_APP_DIR的系统环境变量,把它的值设为D:\myhome\maya。以后Maya会去这文件夹找你的脚本文件。
用记事本把以下这段程序(跟上面一样的)存入一个叫printword.mel的文件,放在D:\myhome\maya\scripts里头。
global proc string printword( string $word, int $num )
{
    int $i;
    for( $i 0; $i $num; $i++ print ($word "\n");
    string $outval "Printed $num words.";
    return $outval;
}
注意程序前面加了个global。若不加的话,Maya就认不到此程序(因为它处在Maya以外的文件)。没加global的程序叫局部程序,只能在脚本里头执行。
在Maya的指令框里先输入source printword,然后输入printword "Try" 4看看。
脚本可以包含任何MEL句子,不一定是程序。比如你可以试在printword.mel最后再加一句
int $j 1;
if ($j) print "$j is true!";

注释
单行句子若用//做开头符号的话,就变成MEL读不到的注释句子。
// This is comment.
// And this is another comment.
多行注释则用 括着。
 
你想下面这段程序会有什么效果?
int $i;
  评论这张
转发至微博

0

阅读 收藏 喜欢 打印举报/Report
后一篇:Mel test
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有