一半君的总结纸

听话只听一半君

#55 如何从已知的多边形面得到相应的点或者边(返回结果按逆时针方向排序 ( “render” order) )?

下图中有一个当前选中的多边形(polymesh)的面(face). 如果我们使用API查询这个面的信息,可以知道Maya是按照如下顺序连接4个点来得到这个面的: 11, 4, 12, 9. 或者也可以说,是按照如下的顺序来生成4条边的: 13, 14, 18, 17.

edges

已知面(Face)求组成该面的所有点(vertex)

polyInfo

“polyInfo” 命令加上 `−faceToVertex` 可以按顺序返回组成此面的所有点. 虽然用tokenize命令可以分拆返回的字符串,拿到想知道的结果(点的序号),但是这不是推荐的方法,不过至少比先得到vertex-face再运行一次才能得到点要简单点 (关于这点下面还有例子).

string $ftv[] = `polyInfo -faceToVertex pPlane1.f[5]`;
// Result: FACE      5:     11      4     12      9

上面的返回结果是一个字符串, 用 tokenize 命令可以得到4个点的序号. 在下面的例子里,根据空格 (” “), 冒号 (“:”), 还有回车/换行 (“\n\r”) 符号来分拆上面返回的字符串,可以得到含有6个elment的字符串数组,第1个element是 “FACE”, 第2个是5, 剩下的4个就是我们要的4个点的序号

string $tokens[];
tokenize $ftv[0] " :\n\r" $tokens;
// Result: 6 //

int $vertexOrder[];
clear $vertexOrder;
int $t;

for ( $t = 2; $t < `size $tokens`; $t++ )
{
  $vertexOrder[`size $vertexOrder`] = $tokens[$t];
};

print $vertexOrder;
// Prints: 11 4 12 9 //

polyListComponentConversion

你也可以用 polyListComponentConversion 命令简介的得到边或者点的顺序(是逆时针顺序,也称为  “render order”, 或者 “construction order”)

Joey Ponthieux (Video Applications Group, NASA Langley Research Center) 给出过下面的例子,首先用 polyListComponentConversion 查询 “vertexFace” ,然后经过一系列转换,最后得到按顺序排列的想要的点或者边.

// This face
ls -sl;
// Result: pPlane1.f[5] //

// Use polyListComponentConversion to get .vtxFace components
string $vtxFace[] = `polyListComponentConversion -fromFace
                                                 -toVertexFace pPlane1.f[5]`;
// Result: pPlane1.vtxFace[11][5]
           pPlane1.vtxFace[4][5]
           pPlane1.vtxFace[12][5]
           pPlane1.vtxFace[9][5] //

上面的结果已经可以看出点的顺序了.但是比较长,这是可以再用一次 polyListComponentConversion ,把vertext face 转换成 vertex. 但是必须一次转换一个vertext face; (因为你如果直接用在$vtxFace上,返回的结果就不是按照逆时针顺序来的了)

// An array to store our result
string $vertexOrder[];

for ( $vf in $vtxFace )
{
  // Get vertex for this vtxFace
  string $vertex[] = `polyListComponentConversion -fromVertexFace -toVertex $vf`;

  // And append to our result
  $vertexOrder[ size($vertexOrder) ] = $vertex[0];
}

print $vertexOrder;
// Result: pPlane1.vtx[11]
           pPlane1.vtx[4]
           pPlane1.vtx[12]
           pPlane1.vtx[9] //

点的序号里有冒号怎么办 pPlane1.f[3:5]
edges2
有时候polyListComponentConversion 命令返回的结果里有”:”:

ls -sl;
// Result: pPlane2.f[4] //

string $vtxFace[] = `polyListComponentConversion -fromFace
                                                 -toVertexFace pPlane2.f[4]`;
// Result: pPlane2.vtxFace[5:6][4]
           pPlane2.vtxFace[10][4]
           pPlane2.vtxFace[9][4] //

上面的结果中,5和6是相邻的,所以被显示到一起去了,这时可以用filterExpand 来展开:

// 可以用filterExpand 来展开 $vtxFace里所有的 .vtxFace component
$vtxFace = `filterExpand -sm 70 -expand true $vtxFace`;
// Result: pPlane2.vtxFace[5][4] pPlane2.vtxFace[6][4]
           pPlane2.vtxFace[10][4] pPlane2.vtxFace[9][4] //

for ( $vf in $vtxFace )
{
  // Get vertex for this vtxFace
  string $vertex[] = `polyListComponentConversion -fromVertexFace -toVertex $vf`;

  // And append to our result
  $vertexOrder[ size($vertexOrder) ] = $vertex[0];
}

print $vertexOrder;

// Result: pPlane2.vtx[5]
           pPlane2.vtx[6]
           pPlane2.vtx[10]
           pPlane2.vtx[9] //

已知面(Face)求组成他的所有Edge (按顺序)

polyInfo

“polyInfo” 命令加`−faceToEdge` 参数可以返回所有组成此面的边(edge), 像上面一样也可以用tokenize来解析返回的字符串,得到所有edge, 或者先得到vertex-face ,然后再得到edge (下面有例子).

string $fte[] = `polyInfo -faceToEdge pPlane1.f[5]`;
// Result: FACE      5:     13     14     18     17

同样使用tokenize命令,分隔符是 空格 (” “), 冒号 (“:”), 还有回车/换行 (“\n\r”) 符号

string $tokens[];
tokenize $fte[0] " :\n\r" $tokens;
// Result: 6 //

int $edgeOrder[];
clear $edgeOrder;
int $t;

for ( $t = 2; $t < `size $tokens`; $t++ )
{
  $edgeOrder[`size $edgeOrder`] = $tokens[$t];
};

print $edgeOrder;
// Prints: 13 14 18 17 //

polyListComponentConversion

上面已经得到了 $vtxFace 字符串数组, 然后可以用polyListComponentConversion 命令加上`−toEdge` flag 来得到所有的edge (按逆时针顺序)

// An array to store our result
string $edgeOrder[];

for ( $vf in $vtxFace )
{
  // Get edge for this vtxFace
  string $edge[] = `polyListComponentConversion -fromVertexFace -toEdge $vf`;

  // And append to our result
  $edgeOrder[ size($edgeOrder) ] = $edge[0];
}

print $edgeOrder;

// Result: pPlane2.e[9]
           pPlane2.e[12]
           pPlane2.e[18]
           pPlane2.e[10] //

Note: Joey Ponthieux 说上面的转换到 edge 的代码只有在 Maya v3.0 或者以上才能用. 在 Maya 2.5 里上面的返回结果不是按顺序来的,所以2.5里必须向下面这样用 ‘−internal’ ,指定下一个vertex,以此来得到这两个vertex之间的edge. ( 现在都2014了,我就不转换下面这段成python了)

// Modified loop to accomodate Maya v2.5
// $vertexOrder derived in method described above
for ( $v = 0; $v < size($vertexOrder); $v++ )
{
  int $nextVtx = ( $v < ( size($vertexOrder) - 1 ) ? $v + 1 : 0 );

  // Use two successive vertices to derive internal edge
  string $edge[] = `polyListComponentConversion -fromVertex -toEdge
                    -internal $vertexOrder[$v] $vertexOrder[$nextVtx]`;

  $edgeOrder[ size($edgeOrder) ] = $edge[0];
}

print $edgeOrder;

// Result: pPlane2.e[9]
           pPlane2.e[12]
           pPlane2.e[18]
           pPlane2.e[10] //

已知边(Edge)求Vertex(按顺序)

这里的”vertex order” 指的是生成Face的时候遵循的同样顺序(这个顺序和face的normal方向是有关的,你只要吧顺序反过来,face的normal就朝另外一边了)

因为内侧的edge都是被相邻的两个face共享的,虽然两个faces 都是逆时针生成的, 但是他们的共有的edge的vertex order 是相反的. 假设 face ‘A’ 和 face ‘B’有一条共享的edge,   face ‘A’ 的edge的vertex order和face ‘B’的edge的vertex order是烦的. 所以,如果想要得到一条edge的vertex order,那必然得还得先知道你想求的edge是哪个face上的.

用上面的pPlane1的例子,face 5的 vertex 是 11, 4, 12, 9.  如果按这个顺序来生成edge的话,edge的顺序是: { 11,4 }, { 4,12 }, { 12,9 }, { 9,11 }.

把上面讨论过的方法综合起来就可以从edge求vertex了. 步骤如下:

从指定的face得到ordered vertices, (见 “Deriving Vertex Order From A Face”.)

从第一个 vertex开始, 找到下一个vertex, 组成一对,从而得到edge (见 “Deriving Edge Order From A Face”.)

如果上一步得到的 edge 是指定的 edge, 那么现在的一对vertex pair,就是我们要求得vertex order(正在指定的edge上和指定的face上.

如果所有的 vertex 对都试过了,还是找不到符合的edge,那说明指定的 edge 不在指定的 face 里,此时返回空.

polyInfo

polyListComponentConversion

下面的 MEL procedure 的 arguments 是 edge 和相应的 face , 返回一个字符串数组(string array),其中包含有正确顺序的 vertex pair (组成已知edge的)

global proc string[] edgeVertexOrder( string $inputEdge, string $inputFace )
{
  string $edgeVertexOrder[];

  string $vertexOrder[];

  // Note: polyListComponentConversion will return the components relative
  //       to the TRANSFORM node.  You may want to add an assertion/conversion
  //       for the input arguments so they are relative to a transform.
  //       If the input arguments are shape-relative then this procedure will FAIL.

  // Get vertex order of face
  string $vtxFace[] = `polyListComponentConversion -fromFace -toVertexFace $inputFace`;

  // Use filterExpand to individualize each .vtxFace component in $vtxFace
  $vtxFace = `filterExpand -sm 70 -expand true $vtxFace`;

  for ( $vf in $vtxFace )
  {
    // Get vertex for this vtxFace
    string $vertex[] = `polyListComponentConversion -fromVertexFace -toVertex $vf`;

    // And append to our result
    $vertexOrder[ size($vertexOrder) ] = $vertex[0];
  }

  // Now, check each vertex pair to see if it matches the specified edge
  for ( $v = 0; $v < size($vertexOrder); $v++ )
  {
    int $nextVtx = ( $v < ( size($vertexOrder) - 1 ) ? $v + 1 : 0 );

    // Use two successive vertices to derive internal edge

    string $edge[] = `polyListComponentConversion -fromVertex -toEdge
                    -internal $vertexOrder[$v] $vertexOrder[$nextVtx]`;

    // Does this match?
    if ( $edge[0] == $inputEdge )
    {
      $edgeVertexOrder[0] = $vertexOrder[$v];
      $edgeVertexOrder[1] = $vertexOrder[$nextVtx];

      // As soon as a match is found we can stop looking.
      break;
    }
  }

  // Warn if $inputEdge not found in $inputFace
  if ( size( $edgeVertexOrder ) == 0 )
    warning ( $inputEdge + " is not part of " + $inputFace );

  return $edgeVertexOrder;
}

运行结果:

edgeVertexOrder pPlane1.e[18] pPlane1.f[6];
// Result: pPlane1.vtx[9] pPlane1.vtx[12] //

// This demonstrates that the adjacent face (.f[277]) evaluates its
// vertex order in the opposite direction, as described in the text.
//
edgeVertexOrder pPlane1.e[18] pPlane1.f[5];
// Result: pPlane1.vtx[12] pPlane1.vtx[9] //

edgeVertexOrder pPlane1.e[18] pPlane1.f[7];
// Warning: pPlane1.e[18] is not part of pPlane1.f[7] //

感谢

  • Joey Ponthieux, Video Applications Group, NASA Langley Research Center, for demonstrating how to use “polyListComponentConversion”
  • David Biggs, for prompting me to update this How-To with “polyInfo”

Related How-To’s

18 Sep 2004

Advertisements

发表评论

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 更改 )

Twitter picture

You are commenting using your Twitter account. Log Out / 更改 )

Facebook photo

You are commenting using your Facebook account. Log Out / 更改 )

Google+ photo

You are commenting using your Google+ account. Log Out / 更改 )

Connecting to %s

%d 博主赞过: