mel语初解之二-多边型建模(2)
这是一些必须记住的单词,相信所有学过Maya的人都不会感到陌生。
单词 缩写 解释
polygon poly 多边形
vertex v;ver;vert;vtx 多边形顶点
edge e;ed 多边形边线
face f 多边形面
split 切割
index idx 索引
要编写一个比较复杂的程序,我们首先考虑的是应该怎样把这个程序做最大程度的简化,要把一个庞大的东西拆成一小块
一小块的分别去处理。今天我们需要完成第一小块,就是当你选择一条边时,程序可以在这条边的两侧各切一刀,如图。
要做到这一点,需要分成四步。
第一步,我们需要做一点准备工作,要了解一下切割命令polySplit和边的构造顺序。
为了更直观的说明程序的原理,我尽量多放一些插图。
选择菜单Polygons->Create Polygon Tool,从左上角开始,画一个正方形。这时看看mel历史窗,可以看到polyCreateFacet命令,这个命令目前还用不到,先不去管他。
依次选择正方形的四个顶点,看看每个顶点的名称和索引号。
可以发现索引号是按照创建时的顺序指定的。分别为0,1,2,3。
再看看每条边的索引号,也是按照创建时的顺序指定的。一条边有两个点,分别为起点和终点,这两个点决定了边的构造顺序。
使用Edit Polygons->Split Polygon Tool在正方形上切一刀。
我们看一下polySplit的用法,-ep后面有两个参数,第一个参数(3)是边的索引号,第二个参数(0.263489)是百分比,如果边的长度为1,切割点在边的0.263489处。
切割点位置的受到边的构造顺序的影响,以polySurface1.e[3]这条边为例,从边的起点开始,沿着边的终点方向量出整条边的约26%的长度,这个位置就是切割点的位置。
使用polySplit的一大难点就是判断边的构造顺序,也就是分清边的起点和终点。为了做到这一点,我们需要用到一个mel命令 - polyInfo。
选择一条边线(e[3]),在命令行执行"polyInfo -ev;",可以看到输出结果"// Result: EDGE 3: 3 0 Hard",其中"EDGE 3:"代表边线(e[3]),3和0分别代表组成这条边的两个点(vtx[3]和vtx[0])的索引号。注意,这两个点的顺序不是按大小排列的,而是按照边线的构造顺序。
我们把polyInfo按照自己的需要封装起来。主要是用字符处理的方法实现的,注意这里用到了一个前面讲过的工具函数getBaseName()。你会发现这个函数的用途与getVerts()很像,但getVerts()无法得知边线的构造顺序。
// 根据一条边,得到这条边的按构造顺序排列的两个端点。
proc string[] edge2Vertex(string $edge)
{
string $verts[], $buffer[];
string $edgeInfo[] = `polyInfo -ev $edge`;
int $nbVertex = tokenize($edgeInfo[0], $buffer);
string $polyName = getBaseName($edge);
$verts[0] = $polyName + ".vtx[" + $buffer[2] + "]";
$verts[1] = $polyName + ".vtx[" + $buffer[3] + "]";
return $verts;
}
第二步,我们要找到需要切割的两条边。
我们可以根据选择的一条边,和要切割的那个面来判断。
选择一条边。Mel历史窗中的代码: select -r polySurface1.e[6] ;
Edit Polygons->Selection->Convert Selection to Vertices,转换成顶点。
[注] 这一步mel历史窗中可能看不到变化,按z键undo一下就看到了。
Mel历史窗中的代码: ConvertSelectionToVertices;
再选择Edit Polygons->Selection->Convert Selection to Edges,转换成边。
Mel历史窗中的代码: ConvertSelectionToEdges;
去掉开始那条边的选择。
Mel历史窗中的代码: select -tgl polySurface1.e[6] ;
[注] select -d polySurface1.e[6] ;也可。
[注] select -d polySurface1.e[6] ;也可。
现在剩下四条边,可以用getSelEdges()把它们存到一个数组中。
数组1:
{"polySurface1.e[1]",
"polySurface1.e[3]",
"polySurface1.e[4]",
"polySurface1.e[5]"}
选择要切割的面。Mel历史窗中的代码: select -r polySurface1.f[1] ;
用getEdges()把属于面的四条边存到另一个数组中。
{polySurface1.e[0],
polySurface1.e[1],
polySurface1.e[4],
polySurface1.e[6]}
用intersectStringArray()可以找到两个数组的共同部分,就是我们将要切割的两条边。
{polySurface1.e[1],
polySurface1.e[4]}
用getEdges()把属于面的四条边存到另一个数组中。
{polySurface1.e[0],
polySurface1.e[1],
polySurface1.e[4],
polySurface1.e[6]}
用intersectStringArray()可以找到两个数组的共同部分,就是我们将要切割的两条边。
{polySurface1.e[1],
polySurface1.e[4]}
把前面Mel历史窗中记录下的代码整理一下,就成了:
// 已知一个面,这个面的一条边,求与(这个面的)这条边相邻的两条边
proc string[] adjacentEdgesInFace(string $face, string $edge)
{
// 获取所有相邻的边线
select -r $edge;
ConvertSelectionToVertices();
ConvertSelectionToEdges();
select -d $edge;
string $edges_vert[] = getSelEdges();
// 获取已知面的所有边线
select -r $face;
string $edges_face[] = getEdges();
// 求两个数组的共同部分
string $edges[] = intersectStringArray($edges_vert, $edges_face);
return $edges;
}
学习 · 提示
相关教程