欧美少妇被草的嗷嗷叫,国产麻豆色欲啪啪三级片,国产夜夜操,亚洲热女系列第一AV天堂,男人下面插女人下面网站,黄片在线免费观看,大奶子日日日日日,AV色欲亚洲一区,亚洲一级熟妇AV,又粗又长又爽又黄视频

暴雪國際動漫教育
  • 暴雪國際2024招生簡章
  • 暴雪國際2024招生簡章
  • 暴雪國際2024招生簡章
  • 暴雪國際2024招生簡章
在線咨詢 預約課程 網上報名
Maya建模教程

maya建模教程:多邊型建模篇

編輯:張闖來源:暴雪國際教育發(fā)布時間:2010-08-03

再看看每條邊的索引號,也是按照創(chuàng)建時的順序指定的。一條邊有兩個點,分別為起點和終點,這兩個點決定了邊的構造順序。
mel語初解之二-多邊型建模篇

使用Edit Polygons->Split Polygon Tool在正方形上切一刀。
mel語初解之二-多邊型建模篇

我們看一下polySplit的用法,-ep后面有兩個參數,第一個參數(3)是邊的索引號,第二個參數(0.263489)是百分比,如果邊的長度為1,切割點在邊的0.263489處。

切割點位置的受到邊的構造順序的影響,以polySurface1.e[3]這條邊為例,從邊的起點開始,沿著邊的終點方向量出整條邊的約26%的長度,這個位置就是切割點的位置。
mel語初解之二-多邊型建模篇

 

使用polySplit的一大難點就是判斷邊的構造順序,也就是分清邊的起點和終點。為了做到這一點,我們需要用到一個mel命令 - polyInfo。

選擇一條邊線(e[3]),在命令行執(zhí)行"polyInfo -ev;",可以看到輸出結果"// Result: EDGE 3: 3 0 Hard",其中"EDGE 3:"代表邊線(e[3]),3和0分別代表組成這條邊的兩個點(vtx[3]和vtx[0])的索引號。注意,這兩個點的順序不是按大小排列的,而是按照邊線的構造順序。
mel語初解之二-多邊型建模篇

我們把polyInfo按照自己的需要封裝起來。主要是用字符處理的方法實現的,注意這里用到了一個前面講過的工具函數getBaseName()。你會發(fā)現這個函數的用途與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語初解之二-多邊型建模篇

選擇一條邊。

Mel歷史窗中的代碼:
 

select -r polySurface1.e[6] ;


mel語初解之二-多邊型建模篇

Edit Polygons->Selection->Convert Selection to Vertices,轉換成頂點。
[注] 這一步mel歷史窗中可能看不到變化,按z鍵undo一下就看到了。

Mel歷史窗中的代碼:

 

ConvertSelectionToVertices;


mel語初解之二-多邊型建模篇

再選擇Edit Polygons->Selection->Convert Selection to Edges,轉換成邊。

Mel歷史窗中的代碼:

 

ConvertSelectionToEdges;


mel語初解之二-多邊型建模篇

去掉開始那條邊的選擇。

Mel歷史窗中的代碼:

 

select -tgl polySurface1.e[6] ;


[注] select -d polySurface1.e[6] ;也可。
 

現在剩下四條邊,可以用getSelEdges()把它們存到一個數組中。
數組1:
{"polySurface1.e[1]",
"polySurface1.e[3]",
"polySurface1.e[4]",
"polySurface1.e[5]"}
mel語初解之二-多邊型建模篇

選擇要切割的面。

Mel歷史窗中的代碼:

 

select -r polySurface1.f[1] ;


getEdges()把屬于面的四條邊存到另一個數組中。
{polySurface1.e[0],
polySurface1.e[1],
polySurface1.e[4],
polySurface1.e[6]}
mel語初解之二-多邊型建模篇

用intersectStringArray()可以找到兩個數組的共同部分,就是我們將要切割的兩條邊。
{polySurface1.e[1],
polySurface1.e[4]}
mel語初解之二-多邊型建模篇

 

把前面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;
}


第三步,切割一個面。

我們可以先把切割的百分比設置一個固定的數值,設為0.2(20%)。

我們可以通過edge2Vertex()來得到要切割的一條邊的起點和終點,如果起點恰好是當初選擇的那條邊線的一個端點(兩條邊的公共點),那么這條線的構造順序是正的,可以直接使用20%;但如果構造順序是反的,那就要使用1-20%=80%了。
mel語初解之二-多邊型建模篇
 

這個函數應該這么寫:

 

proc splitByPercent(string $edge1, string $edge2, string $inputEdge)
{
// 預設值,百分比為0.2
float $percent = 0.2;
float $percent1 = $percent; // 0.2
float $percent2 = $percent; // 0.2

// 分別獲得三條邊所包含的頂點
string $verts1[], $verts2[], $vInput[];
$vInput = edge2Vertex($inputEdge);
$verts1 = edge2Vertex($edge1);
$verts2 = edge2Vertex($edge2);

// 求$edge1與$inputEdge的公共點
string $startVert[] = intersectStringArray($verts1, $vInput);
// 如果公共點不是$edge1的起點
if ($startVert[0] != $verts1[0])
// 百分比變?yōu)?0%,即1-0.2
$percent1 = 1 - $percent;

// 求$edge2與$inputEdge的公共點
string $startVert[] = intersectStringArray($verts2, $vInput);
if ($startVert[0] != $verts2[0])
$percent2 = 1 - $percent;

// 獲得兩條邊的索引號
string $index1 = getIndex($edge1);
string $index2 = getIndex($edge2);

// 準備命令字符串
string $cmd = "polySplit -ch on -s 1 ";
$cmd += "-ep " + $index1 + " " + $percent1 + " ";
$cmd += "-ep " + $index2 + " " + $percent2 + " ";
$cmd += ";";

// 選擇整個多邊形物體
string $polyName = getBaseName($edge1);
select -r $polyName;

// 執(zhí)行命令
evalEcho($cmd);
}

[注] 使用evalEcho執(zhí)行命令可以把命令字符串在mel歷史窗中顯示出來。

第四步,切割邊線兩邊的面。

有了前面的準備工作,最后一步就顯得比較容易了。

 

global proc myEdgeChamfer()
{
// 獲取選擇的一條邊
string $edges[] = getSelEdges();
string $inputEdge = $edges[0];

// 獲取選擇的邊相鄰的兩個面
string $faces[] = getFaces();

// 等比切割第1個面
string $splitEdges[];
$splitEdges = adjacentEdgesInFace($faces[0], $inputEdge);
splitByPercent($splitEdges[0], $splitEdges[1], $inputEdge);

// 等比切割第2個面
$splitEdges = adjacentEdgesInFace($faces[1], $inputEdge);
splitByPercent($splitEdges[0], $splitEdges[1], $inputEdge);
}


附全部源代碼。

 

///////////////////////////////////////////////////////////
// myEdgeChamfer.mel
// myEdgeChamfer v1

// 獲取選擇的多邊形頂點
proc string[] getSelVerts()
{
return `filterExpand -ex true -sm 31`;
}

// 獲取選擇的多邊形邊
proc string[] getSelEdges()
{
return `filterExpand -ex true -sm 32`;
}

// 獲取選擇的多邊形面
proc string[] getSelFaces()
{
return `filterExpand -ex true -sm 34`;
}

// 根據點、邊、面、UV點的名稱得出多邊形的名稱
// 例如多邊形一條邊的名稱為"pSphere1.e[637]",則這個多邊形的
// 名稱為"pSphere1"
proc string getBaseName(string $item)
{
string $buffer[];
if ($item != "")
{
tokenize($item, ".", $buffer);
}
return $buffer[0];
}

// 根據點、邊、面、UV點的名稱得出它們的索引號
// 例如多邊形一條邊的名稱為"pSphere1.e[637]",則這個多邊形的
// 索引號為637
proc int getIndex(string $indexString)
{
string $buffer[];
tokenize($indexString, "[]", $buffer);
int $index = (int)$buffer[1];
return $index;
}

// 獲得兩個數組的共同部分
proc string[] intersectStringArray(string $array1[], string $array2[])
{
global string $m_arrayIntersector;
if ($m_arrayIntersector == "")
$m_arrayIntersector = `stringArrayIntersector`;

stringArrayIntersector -edit -intersect $array1 $m_arrayIntersector;
stringArrayIntersector -edit -intersect $array2 $m_arrayIntersector;
string $result[] = `stringArrayIntersector -query $m_arrayIntersector`;
stringArrayIntersector -edit -reset $m_arrayIntersector;
return $result;
}

///////////////////////////////////////////////////////////
// 第一步,根據一條邊,得到這條邊的按構造順序排列的兩個端點。
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;
}

// 已知一個面,這個面的一條邊,求與(這個面的)這條邊相鄰的兩條邊
proc string[] adjacentEdgesInFace(string $face, string $edge)
{
// 獲取所有相鄰的邊線
select -r $edge;
ConvertSelectionToVertices();
ConvertSelectionToEdges();
select -d $edge;
string $edges_vert[] = getSelEdges();

// 獲取已知面的所有邊線
sele ct -r $face;
string $edges_face[] = getEdges();

// 求兩個數組的共同部分
string $edges[] = intersectStringArray($edges_vert, $edges_face);
return $edges;
}

// 第三步,等比切割一個面
proc splitByPercent(string $edge1, string $edge2, string $inputEdge)
{
// 預設值,百分比為0.2
float $percent = 0.2;
float $percent1 = $percent; // 0.2
float $percent2 = $percent; // 0.2

// 分別獲得三條邊所包含的頂點
string $verts1[], $verts2[], $vInput[];
$vInput = edge2Vertex($inputEdge);
$verts1 = edge2Vertex($edge1);
$verts2 = edge2Vertex($edge2);

// 求$edge1與$inputEdge的公共點
string $startVert[] = intersectStringArray($verts1, $vInput);
// 如果公共點不是$edge1的起點
if ($startVert[0] != $verts1[0])
// 百分比變?yōu)?0%,即1-0.2
$percent1 = 1 - $percent;

// 求$edge2與$inputEdge的公共點
string $startVert[] = intersectStringArray($verts2, $vInput);
if ($startVert[0] != $verts2[0])
$percent2 = 1 - $percent;

// 獲得兩條邊的索引號
string $index1 = getIndex($edge1);
string $index2 = getIndex($edge2);

// 準備命令字符串
string $cmd = "polySplit -ch on -s 1 ";
$cmd += "-ep " + $index1 + " " + $percent1 + " ";
$cmd += "-ep " + $index2 + " " + $percent2 + " ";
$cmd += ";";

// 選擇整個多邊形物體
string $polyName = getBaseName($edge1);
select -r $polyName;

// 執(zhí)行命令
evalEcho($cmd);
}

// 第四步,切割選擇的一條邊線兩邊的面。
global proc myEdgeChamfer()
{
// 獲取選擇的一條邊
string $edges[] = getSelEdges();
string $inputEdge = $edges[0];

// 獲取選擇的邊相鄰的兩個面
string $faces[] = getFaces();

// 等比切割第1個面
string $splitEdges[];
$splitEdges = adjacentEdgesInFace($faces[0], $inputEdge);
splitByPercent($splitEdges[0], $splitEdges[1], $inputEdge);

// 等比切割第2個面
$splitEdges = adjacentEdgesInFace($faces[1], $inputEdge);
splitByPercent($splitEdges[0], $splitEdges[1], $inputEdge);
}


寫到大括號里就成了局部變量。

寫到大括號外面就是全局變量,不過這時 float $bb = 5 ; 和 global float $bb = 5 ; 還是有一點點差別的,很容易讓人忽略。就是如果不寫global,包含這句代碼的mel文件如果不被source,只是執(zhí)行了mel文件的同名函數,那么$bb載入內存時將不被賦值,這時$bb的值為 0。所以說最好寫上global。

下面我想講一下關于全局變量和局部變量的區(qū)別吧.
如何定義全局變量呢,定義全局變量必須在所有自定義函數的外邊,不能定義在{}里面:
global int $a;//定義了全局變量,默認值是0
如果要調用的話:
proc myfn()
{
global int $a;//在調用全局變量的時候必須在自己的函數里面在定義一下
$a=10;
.....
}
//這樣就是調用的過程
強調一點的是,要想調用全局變量就必須在自己的函數里面在重新定義一邊.不燃的話,你試試看...呵呵

局部變量就是:
int $a;// 不加global 的
但是所有的變量都有生命期的,所謂的生命期就是在一定的范圍內有效...
proc myfn()
{
int $a=10;
if($a<20)
{
$a++;
.........
print $a;//reslut 11;
}
print $a;//result 11,而不是10了
.........
}
這樣就是生命期,如果你在后面還調用的話,$a就不是10了,就是11了....

我還想講一下的就是,正如七月冰兒講的一樣,如果想得到幾個邊的名稱的話,
你會發(fā)現所有的名稱都是按照從小到大的順序進行排序的來的,這樣有好處也有壞處,壞處就是有時后我不想得到是排列之后的名稱,我之想得到不排列的名稱...
這也是多邊形的切割工具一直很麻煩的原因,總不能想3dmax那樣隨心所欲的進行切割了....
但是辦法是有的,目前我沒有想好,也許七月冰兒在他以后的版本里會出現這樣的功能的....
我也在思索這個問題,其實大家在使用的過程當中,完全可以作出好多的快捷的功能的,就想在調權重值一樣,雖然maya提供了cmeditor,但還是很不方便的...
以后接著說,希望大家都能夠參與近來呀
 

假如你有一個mel文件,文件名為myTest.mel,文件內容如下:

 

float $bb = 5;
global proc myTest()
{
// do nothing
}


啟動Maya,使用env命令查看一下當前的全局變量,可以發(fā)現此時變量$bb不存在。當執(zhí)行myTest命令時,這時$bb作為全局變量載入內存,再用env命令查看一下,發(fā)現$bb已經存在了。但是執(zhí)行print $bb;會看到結果為0。

重新啟動Maya,啟動后執(zhí)行source myTest.mel;這時再執(zhí)行print $bb;可以看到輸出了正確的結果5,這時$bb已經作為全局變量載入了內存。

這就是我說的如果不寫global,包含這句代碼的mel文件如果不被source,只是執(zhí)行了mel文件的同名函數,那么$bb載入內存時將不被賦值,這時$bb的值為 0。

如果你只是(在所有大括號外面)聲明變量,在函數中給它賦值,就可以不寫global了。比如代碼改成這樣就沒問題了。

 

// 在Maya6.0中測試通過
float $bb;
global proc myTest()
{
global float $bb;
$bb = 5;
}


如果想在函數外面聲明和使用變量,又不想讓Maya當作全局變量,可以加大括號,函數的生命在大括號結束時消亡。例如:
 

{
float $bb;
... ...
}


關于全局變量的用法,可以參考junesnow的說明,不過要注意我做的一點更正。
 


 

首頁 上一頁 1 2

上一篇:maya建模教程:利用貫穿動態(tài)拉出一造型物

下一篇:maya建模教程:卡通螞蟻的制作