您现在的位置:首页 > CG教程 > 其他专栏 > 程序脚本 > 文章内容
maya mel 基础理论 RSS订阅

maya mel 基础理论

发表时间:2005-10-25

   六、定义数据 top
   本章描述MEL的数据类型它们之间的转换:1、变量;2、常数;3、数据类型转换;4、限制。
   1、变量
   所有变量名以$开始。变量名不包括空格和特殊字符。你可以使用下划线和数字作为变量名但开头不能是数字。识别大小写,如$temp不同于$Temp。例:
   int $radical7Mark; // 有效
   int HEYchief; // ERROR: 开头缺"$"
   int $ nine; // ERROR: 开头不是"$"
   int $_VAL_ID___AIT_; // 有效
   int $howdyYa`ll; // ERROR: 含有无效字符
   int $1Bill; // ERROR: 开头不能是数字
   有以下五种变量类型:
   类型 意义 例子
   int 整数 (...-2, -1, 0, 1, 2...)10, -5, 和 0
   float 小数 392.6, 7.0, and -2.667
   string 一个或更多的字符 "What's up, chief?"
   vector 三个浮点数 <<3,?7.7,?9.1>>
   matrix 浮点数阵列 <<1.1, 2, 3; 6.7, 5, 4.9>>
   以上类型除matrix外,都可以是一个阵列。如,一个三元素的整数阵列是一个跟一个的三个整数。
   声明和标注变量
   声明一个变量是说明变量的名字和类型;标注一个变量是给已生命的变量一个专有的值。下例是将声明和标注合为一步:
   int $temp = 3;
   float $Temp = 222.222;
   string $tEmp = "Heya kid.";
   vector $teMp = <<1, 2.7, 3.2>>;
   matrix $temP[2][3] = <<4.5, 1, 0.2; -13, 9911, 0.007>>;
   当生命矩阵变量时,必须包括二维阵列的尺寸。
   下例说明对整型、浮点、字符串和矢量阵列型变量阵列的声明和标注:
   int $TEmp[5] = {100, 1000, -70, 2, 9822};
   float $TeMp[4] = {43.3, -10.7, 0, 82.5};
   string $TemP[3] = {"Lord", "Flies", "cool brown fox2."};
   vector $tEMp[2] = {<<0, 0, 0>>, <<0.01, -2, 16>>};
   如果一个变量被声明但未被标注,它的所有的值是0;字串变量则?quot; "。
   float $teMP; // 赋值: 0;
   string $TEMp[3]; // 赋值: {"", "", ""};
   vector $TEmP[2]; // 赋值: {<<0, 0, 0>>, <<0, 0, 0>>};
   matrix $TeMP[3][2]; // 赋值: <<0, 0; 0, 0; 0, 0>>;
   如果一个变量被声明或者被使用而没有定义它的类型,它被隐含声明为将要赋值给它的那种类型。
   $tEMP = 0.0; // 浮点数
   string $TEMP[]; // 零元素字符串阵列
   $trip = "heya Buddy"; // 字符串
   $rip = {1, 2, 3, 4}; // 四元素整型阵列
   $lip = <<1, 2.1; 3, 4>>; // 2X2 矩阵
   $flixp = $TEMP; // 零元素字符串阵列
   注意值0.0是一个浮点数,而一个0值是一个整型数。这决定了在隐含声明时是产生一个浮点数还是产生一个整型数。 不建议使用隐含声明,因为它不象变量的隐含声明那样的清楚。
   保留字
   MEL的保留字可以是一个变量类型、控制逻辑或是表达一个值。以下是MEL的保留字:
   break case continue default do else
   false float for global if in
   int matrix no off on proc
   return string switch true vector while
   yes
   数据类型关键字
   int float vector string matrix
   布尔常数关键字
   yes no on off true false
   流动控制关键字
   if else for while do in break continue default switch case
   其他关键字
   global return source catch alias proc
   保留字也区分大小写。所以int是整型,Int不是。实际上alias、source、catch 也是保留字,但它们起指令作用,因此没有被包括在上述表内。
   2.字符串
   字符串可用"+"运算连接。
   string $what = "Whale";
   string $title = "Great" + " White " + $what;
   这将使title变量的内容为Great White Whale。
   3.矢量
   为寻址一个vector的各个成分,使用"."。
   vector $LOS = <<1, 2, 7>>;
   float $firstComponent = $LOS.x; // 赋值为 1
   float $secondComponent = $LOS.y; // 赋值为 2
   float $thirdComponent = $LOS.z; // 赋值为 7
   标注矢量的成分:
   vector $LOCK = <<7, -4, 9>>;
   $LOCK = <<$LOCK.x, $LOCK.y, 3>>; // Assigned <<7, -4, 3>>
   但不能直接给一个成分标数字:
   $LOCK.z = 3000; // 错误
   但是通常当访问一个矢量成分时,你应该象下面例子那样围绕它使用括号:
   例子:
   print $LOCK.x; // 错误
   print($LOCK.x);
   setAttr persp.scaleX $LOS.x; // 错误
   setAttr persp.scaleX ($LOS.x);
   4.阵列
   你可以声明一个int, float, string或vector类型的阵列。阵列的第一个序号为0。
   string $array[3] = {"first\n", "second\n", "third\n"};
   print($array[0]); // 显示 "first\n"
   print($array[1]); // 显示 "second\n"
   print($array[2]); // 显示 "third\n"
   阵列尺寸可以自动地增加。
   int $scores[]; // 声明为一个0元素阵列
   $scores[150] = 3; // 现在是151元素阵列
   $scores[200] = 5; // 现在是201元素阵列 但最好不要声明过大的没用的阵列,因为它要占内存:
   int $bigBoy[];
   $bigBoy[123456789] = 2; // 危险
   要除去一个阵列的所有元素可使用clear功能。要查看阵列的尺寸可使用size。
   string $hats[3] = {"blue", "red", "black"};
   print("There were " + size($hats) + " hats.\n");
   clear($hats);
   print("But now there are " + size($hats) + ".\n");
   以上指令的输出是:
   There were 3 hats.
   But now there are 0.
   5.矩阵
   可以把一个矩阵想象为一个浮点阵列的阵列,或是一个浮点数据的二维阵列。矩阵产生后,它的尺寸不能改变。 企图寻址一个矩阵的不存在的元素将会出现错误。在产生矩阵时必须定义它的尺寸。
   matrix $a1[][] = <<1; 4>>; // 错误: 没有说明尺寸
   matrix $a2[][]; // 错误: 没有说明尺寸
   matrix $a3[2][1]; // 有效: 产生 <<0; 0>>;
   $a3[0][1] = 7; // 错误: 元素不存在
   $a3[1][0] = 9; // 有效
   声明而未标注值的矩阵,其所有元素都为0。
   matrix $a4[2][4] = <<-3.4, 6, 201, 0.7; 4, 2, 9.3, 1001>>; 如果矩阵表示一个二维阵列,则第一个索引表示列;地二个索引表示行:
   matrix $a4[2][4]column 0column 1column 2column 3
   row 0-3.462010.7row 1429.31001
   如果你把矩阵设想为一个身列的阵列,则第一个索引表示阵列,第二个索引该阵列里的索引:
   matrix $a4[2][4]index 0index 1index 2index 3
   float array 0-3.462010.7float array 1429.31001
   6.物体属性
   属性是场景中的物体的特征或参数。在Maya中可以用许多方法建立属性-属性编辑器、MEL程序、工具盒工具或表达式。你可以设立属性去控制在工作空间中看到的虚拟的事情。如,一个NURBS球具有属性scaleX, scaleY, scaleZ, rotateX, 等等。

   物体属性名
   物体属性名具有如下格式:
   objectName.attributeName
   其中objectName是物体的名字,attributeName是该物体的属性名。属性名中不要使用空格或特殊字符,可以用下划线。产生一个名字为Brawl的球:sphere -name Brawl; 可以获取它的属性的一个值:float $yScale = `getAttr Brawl.scaleY`; Brawl.scaleY是Brawl物体的scaleY属性的全名。
   7.路径
   如果两个物体具有不同的父物体,它们可以有相同的名字。当说明有相同名字的物体时必须使用路径:pathname│objectname其中pathname物体的父物体。管道字符(│)用于区分路径。
   sphere -name doughnutHole;
   group -name GroupA;
   sphere -p 3 0 0 -name doughnutHole;
   现在我们有两个叫做doughnutHole的物体,但一个有父物体GroupA,另一个没有父物体。以下指令产生一个错误,因为Maya不知道哪个doughnutHole物体要设立scaleY属性:
   setAttr doughnutHole.scaleY 3.3; // ERROR: 哪个?你必须输入属性的路径:
   setAttr GroupA│doughnutHole.scaleY 3.3;
   setAttr │doughnutHole.scaleY 0.3; 你可以说明物体的所有路径,用管道符进行区分:group -name GroupB GroupA; setAttr │GroupB│GroupA│doughnutHole.scaleY 1; 物体属性的可能的数据类型,每个属性有特定的数据类型。几何体, 粒子物体, Maya中的其他项都具有这些数据类型的属性:
   数据类型 意义 属性例 数据例
   浮点小数 numbers Ball.translateX 2.6, 7.0, -9.1int
   整数 (...-1, 0, 1, 2...) BallShape.spansU -289, 33, 0
   boolean 0或1 Ball.visibilityon, off, yes, no, 1, 0, true, false
   考虑一个由以下指令产生的叫做Fire的粒子物体:
   particle -name Fire -position 7 0 7;
   它可以具有以下另外的数据类型:
   数据类型 意义 属性例 数据例
   vector array 矢量阵列 FireShape.position
   {<<3.2,?7.7,?9.1>>, <<7,?10,?2.2>>}
   double array 浮点阵列 numbersFireShape.lifespan 1.333 1.666
   你可以使用getParticleAttr和setParticleAttr指令设立矢量的元素或一个粒子系统的双阵列。
   float $Tmp[] =`getParticleAttr -at position FireShape.pt[0]`;
   vector $particlePosition = <<$Tmp[0], $Tmp[1], $Tmp[2]>>;
   setParticleAttr -at position -vv 0 0 7 FireShape.pt[0];
   对于矢量阵列数据类型,Maya用一个阵列的单元素对物体的每一部分表达指定的属性。注意,pt[0] 表达产生FireShape的第一部分的索引。每个元素是由三个浮点数构成的。在一个双阵列中,Maya用一个浮点数对每一部分表达特定的属性。
   重要事项:在表达式中,你可以使用一个等于符号(=)设立或得到一个变量或属性的值。在MEL语句中,只可以使用(=)设立或得到一个变量值。使用MEL setAttr、getAttr、setParticleAttr、getParticleAttr指令设立或得到一个属性值。
   全局和局部变量 典型地,你将使用在一个单序列里的变量这些变量叫做局部变量(local variables),
因为它们只出现在局部过程里:
   float $tester;如果你产生一个相同名字的局部变量在两个序列里,两个变量被分离并且相互无关。如:假定你在两个序列中产生一个取名为$tester的变量。标注或修改$tester变量的一个值不影响在其他里的值。如果你想在一个序列里产生并动画一个变量,也要把它使用于该序列之外,你可以把它声明为一个全局变量(global variable)。
   global float $counter;
   你就可以用其它MEL指令和语句读该变量。当你要扩大该变量的使用范围时, 应再次进行声明。
   global float $crash = 8;
   global proc holy()
   {
   $crash = 7;
   print($crash + "\n");
   }
   print($crash + "\n"); // 结果:8
   holy(); // 结果:7
   print($crash + "\n"); // 结果:8
   尽管看起来使用了全局浮点型的crash,实际上使用了一个隐含产生的局部整型变量
   (看例子: 隐含声明(Implicit declaration))。
   global float $slash = 8;
   global proc moly()
   {
   global float $slash;
   $slash = 7;
   print($slash + "\n");
   }
   print($slash + "\n"); // 结果:8
   moly(); // 结果:7
   print($slash + "\n"); // 结果:7
   当你用了一个单指令声明了一个全局变量并给它标注了一个值,该标注仅发生在由Maya第一次读指令的时候。 被定义了的序列中的全局变量是被读的。
   global proc proof()
   {
   global float $fight = 7;
   $fight = 2;
   print($fight + "\n");
   }
   知道该序列的proof被读入,变量fight没有声明。换言之,Maya还没有觉察到它的变量的存在。但是,一旦该序列被读入和被定义,该变量fight被声明为一个全局浮点型并被赋值为7。 该声明之后,该全局变量对所有的MEL指令都是可见的。即它可被任何MEL指令修改。但是,当proof被执行后,fight被赋值为2。
   如:在proof被定义后,以下指令将产生给出的结果:

print($fight + "\n"); // Result: 7
proof; // Result: 2
print($fight + "\n"); // Result: 2

如果两个序列对相同的全局变量声明和标注一个值会出现什么情况?看以下两个脚本文件:
(假定放在你的脚本目录中):

脚本文件: crush.mel

global proc crush()
{
global float $sight = 7;
print $sight;
}

脚本文件: groove.mel

global proc groove()
{
global float $sight = 9;
print $sight;
}

一个值标注到一个全局变量仅仅是在第一次Maya读每个脚本文件时。

crush(); // Result: 7
groove(); // Result: 9
crush(); // Result: 9

-------------------------------------------------------------------
2、常数

   MEL中的常数只有布尔常数(Boolean constants)。它实际上是整型数,值为1或者为0。
关键字true, on, 和yes具有值1;关键字false, off 和 no具有值0。
-------------------------------------------------------------------
3、数据类型转换

转换为
-------------------------------------------------------------------
int float string vector matrix
-------------------------------------------------------------------
int ($i) perfect perfect perfect <<$i, $i, $i>> none
float ($f) without perfect perfect <<$f, $f, $f>> none
fraction
string without perfect if perfect perfect if none
fraction starts with starts with
if starts number, vector or
with number else 0 floats with
,else 0 remaining
elements 0
vector length of length of 3 floats perfect perfect
vector vector separated for [1][3]
without by a space matrix,
fraction else none
matrix for [1][3] for [1][3] none for [1][3] perfect
matrix or matrix or matrix or
smaller, smaller, smaller,
length of length of perfect with
matrix matrix remaining
without elements 0
fraction
-------------------------------------------------------------------

一个标量类型(scalar type)是一个非阵列型。从阵列到标量或从标量到阵列型没有转换。

int $ski = 1.8; // 赋值:1
vector $crads = 1.7; // 赋值:<<1.7, 1.7, 1.7>>
int $wild = " 3.44 dogs"; // 赋值:3
vector $wrd = " 8 2.2 cat"; // 赋值:<<8, 2.2, 0>>
int $my = <<1, 2, 3>>; // 赋值:3
string $oo = <<6, 2.2, 1>>; // 赋值:"6 2.2 1"
matrix $so[1][3] = $wrd; // 赋值:<<8, 2.2, 0>>
float $mole = <<0.3, 0.4>>; // 赋值:0.5
vector $ole = <<2, 7.7>>; // 赋值:<<2, 7.7, 0>>

自动转换

   Maya的自动类型转换使我们可以不考虑它们的状态以及不考虑是否是能接受的类型。以下是它们的规则:
--Strings 支配其他所有类型。
--Vectors 支配floats。
--Floats 支配ints。
--如果一个算子为整型,另一个为浮点型,MEL将整型转换为浮点型。
--在vector和matrix之间,左边的类型起支配作用。
--赋值时,有左边的类型支配。

   在一个赋值操作中,右边的类型被转换到左边的类型。前四条规则在右手的计算期间施用于子表达式;
最终的转换发生在给左边赋值时。 下表是自动类型转换的规则。
-------------------------------------------------------------------
运算 结果的数据类型
-------------------------------------------------------------------
int 运算子 float float
float 运算子 int float
int 运算子 vector vector
vector 运算子 float vector
vector 运算子 matrix vector
matrix 运算子 vector matrix
matrix 运算子 string string
string 运算子 int string
-------------------------------------------------------------------

$var1 = 7 + 1.3; // 类型: float (8.3)
$var2 = 7.9 + 2; // 类型: float (9.9)
$var3 = 2 + <<4, 5, 6>>; // 类型: vector <<6, 7, 8>>
$var4 = 0007 + " Lives!"; // 类型: string ("7 Lives!")

   在最后的例子中,0007是值7的整型,它被转换为一个字符串并与"Lives!"合并。结果是一个字符串,它显式声明var4为值是"7 Lives!"的字符串类型。

显式转换

有两个显式方法把一个类型的值转换给另一个。最常用的方法是在该值前面用括号说明:

$Z = (vector) "<<1, 2, 3>>";// Type: vector (<<1, 2, 3>>
$cools = (float) 7; // Type: float (7)
$ools = (string) 47.554; // Type: string ("47.554")

你也可以采用跟随括号来实现显式转换:

$ly = vector("<<1, 2, 3>>"); // Type: vector (<<1, 2, 3>>
$ooly = int(3.67); // Type: int (3)
-------------------------------------------------------------------
4、限制

整数除法的舍弃

当Maya对常数和没有声明数据类型的变量运行算术运算时,它按照表现形式推测数据类型。如以下指令:

float $where = 1/2; // Result: 0
  Maya推测1和2是整型数,因为它们没有小数点。该表达式用整数1除以整数2。其整数结果是0而余数是1。 Maya不保留该余数。

   由于变量是浮点的,Maya将整数值0转换为浮点数0 (相同值)。 为得到该值的小数成分,需要将一个整数转换为浮点:

float $there = 1/2.0; // 结果: 0.5

float $youGo = float(1)/2;
精度和最大数长

   对于一个字串、矩阵或阵列,最大尺寸仅取决于你的计算机的存储器的有效容量。但是,浮点和整型有精度和最大长度的限制。

   一个整数的最大长度与C 语言中是一样的,决定于机器。大部分计算机中它的范围是-2,147,483,648到2,147,483,647。 一个浮点数的最大长度和精度与C语言中的双精度数是一样的,也取决于机器。浮点有精度限制,在长计算里会积累取舍误差。但它的精度很高(大约15位的精度), 取舍通常不会成问题。

超限折返(Range wrap-around)

   变量有范围限制。如果超出这个范围,会产生不期望的后果。

int $mighty = 2147483647 + 1; // Result: -2147483648
int $radical = -2147483648 - 1; // Result: 2147483647
int $buddy = 2147483648; // Result: -2147483648
int $man = 2147483647 + 2; // Result: -2147483647

   当超出了变量的最大范围,变量的值转折为变量的最小值;反之,若超出最小范围,会转为最大值。

float $GG = 1.5 + 1000000000 * 3; // Result: -1294967294.5

  在这个例子中,按照优先顺序先做乘法。因为是两个整数相乘,所以其结果还是一个整数。
因为它的值超过了整型数的最大范围,所以该值被折返。

另一个例子:

$GG = 1.5 + 1000000000 * 3;
$GG = 1.5 + 3000000000; // 超出整型最大范围
$GG = 1.5 + 3000000000 + (2147483648) - (2147483648.0);
$GG = 1.5 + 3000000000 + (-2147483648) - (2147483648.0);
$GG = 1.5 + 3000000000 - 4294967296;
$GG = 1.5 + -1294967296;
$GG = -1294967294.5;

    评论加载中…
相关文章