當(dāng)前位置:首頁(yè)>軟件教程>maya教程>教程內(nèi)容

mel語(yǔ)初解之二-多邊型建模(3)

來(lái)源: 作者:七月冰兒 學(xué)習(xí):4168人次
第三步,切割一個(gè)面。
我們可以先把切割的百分比設(shè)置一個(gè)固定的數(shù)值,設(shè)為0.2(20%)。我們可以通過(guò)edge2Vertex()來(lái)得到要切割的一條邊
的起點(diǎn)和終點(diǎn),如果起點(diǎn)恰好是當(dāng)初選擇的那條邊線(xiàn)的一個(gè)端點(diǎn)(兩條邊的公共點(diǎn)),那么這條線(xiàn)的構(gòu)造順序是正的,可以直接
使用20%;但如果構(gòu)造順序是反的,那就要使用1-20%=80%了。
這個(gè)函數(shù)應(yīng)該這么寫(xiě):

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

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

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

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

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

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

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

// 執(zhí)行命令
evalEcho($cmd);
}
[注] 使用evalEcho執(zhí)行命令可以把命令字符串在mel歷史窗中顯示出來(lái)。

第四步,切割邊線(xiàn)兩邊的面。

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

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

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

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

// 等比切割第2個(gè)面
$splitEdges = adjacentEdgesInFace($faces[1], $inputEdge);
splitByPercent($splitEdges[0], $splitEdges[1], $inputEdge);
}
附全部源代碼。

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

// 獲取選擇的多邊形頂點(diǎn)
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`;
}

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

// 根據(jù)點(diǎn)、邊、面、UV點(diǎn)的名稱(chēng)得出它們的索引號(hào)
// 例如多邊形一條邊的名稱(chēng)為"pSphere1.e[637]",則這個(gè)多邊形的

// 索引號(hào)為637
proc int getIndex(string $indexString)
{
string $buffer[];
tokenize($indexString, "[]", $buffer);
int $index = (int)$buffer[1];
return $index;
}

// 獲得兩個(gè)數(shù)組的共同部分
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;
}

///////////////////////////////////////////////////////////
// 第一步,根據(jù)一條邊,得到這條邊的按構(gòu)造順序排列的兩個(gè)端點(diǎn)。
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;
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


myEdgeChamfer_v1.rar (1.46k)

等距切割

要想知道一條邊的長(zhǎng)度,如果是Maya5.0或更低版本,可以使用arclen命令,但是到了Maya6.0,arclen命令只支持Nurbs,退化了?

這樣我們不得不用到獲得兩點(diǎn)之間的距離的功能來(lái)計(jì)算邊的長(zhǎng)度,F(xiàn)在要提到一點(diǎn)圖形學(xué)知識(shí),當(dāng)然是最最基礎(chǔ)的,就是"勾股定理"。相信大家都能記得一點(diǎn)"勾股定理"的內(nèi)容,我就不詳細(xì)講了。如果需要詳細(xì)講的話(huà),可以提出來(lái),我可以在后面補(bǔ)充。

"勾股定理"的公式是: a2 + b2 = c2

根據(jù)這個(gè)公式推理出3D空間勾股定理公式:x2 + y2 + z2 = d2

如果求兩點(diǎn)之間的距離,公式如圖:dist為點(diǎn)P1(x1,y1,z1)和P2(x2,y2,z2)之間的距離

根據(jù)公式,我們來(lái)編一個(gè)工具函數(shù)求兩點(diǎn)之間的距離。你也許會(huì)感到奇怪,這么常用的功能,Maya中為什么沒(méi)有內(nèi)置的命令呢?這一點(diǎn)我也感到奇怪,好在編寫(xiě)這樣的功能非常簡(jiǎn)單。

// 計(jì)算兩個(gè)頂點(diǎn)之間的距離
proc float distance2Verts(string $vert1, string $vert2)
{
// 獲取兩個(gè)頂點(diǎn)的坐標(biāo)值
float $p1[] = `pointPosition $vert1`;
float $p2[] = `pointPosition $vert2`;

// 計(jì)算距離
float $distance;
float $v[3];
$v[0] = $p1[0] - $p2[0];
$v[1] = $p1[1] - $p2[1];
$v[2] = $p1[2] - $p2[2];
$distance = $v[0]*$v[0] + $v[1]*$v[1] + $v[2]*$v[2];
$distance = sqrt($distance);// 開(kāi)方

return $distance;
}


[注] 獲取點(diǎn)的坐標(biāo)值還有一種方法是:
float $p1[] = `xform -q -ws -t $ver1`;


[注] 獲取點(diǎn)的坐標(biāo)值還有一種方法是:
float $p1[] = `xform -q -ws -t $ver1`;

現(xiàn)在只要把等比切割的函數(shù)改一改就差不多了,把splitByPercent()改為splitByDist()。我把沒(méi)有改動(dòng)的部分用灰綠色表示,重點(diǎn)看看改動(dòng)的部分。
[注] dist為distance的縮寫(xiě)。

// 第三步,等距切割一個(gè)面
proc splitByDist(string $edge1, string $edge2, string $inputEdge)
{
// 預(yù)設(shè)值,距離為0.2個(gè)單元格
float $dist = 0.2;
float $percent1;
float $percent2;

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


// 計(jì)算第一條邊的切割處
float $edgeLength; // 求第一條邊的長(zhǎng)度
$edgeLength = distance2Verts($verts1[0], $verts1[1]);
if ($edgeLength < $dist) // 如果長(zhǎng)度小于預(yù)設(shè)值0.2
$percent1 = 1; // 切割處在線(xiàn)的的末端
else
$percent1 = $dist / $edgeLength; // 計(jì)算出百分比

// 計(jì)算第二條邊的切割處
$edgeLength = distance2Verts($verts2[0], $verts2[1]);
if ($edgeLength < $dist)
$percent2 = 1;
else
$percent2 = $dist / $edgeLength;

// 求$edge1與$inputEdge的公共點(diǎn)
string $startVert[] = intersectStringArray($verts1, $vInput);
// 如果公共點(diǎn)不是$edge1的起點(diǎn)
if ($startVert[0] != $verts1[0])

// 百分比變?yōu)?-$percent1
$percent1 = 1 - $percent1;

// 求$edge2與$inputEdge的公共點(diǎn)
string $startVert[] = intersectStringArray($verts2, $vInput);
if ($startVert[0] != $verts2[0])

$percent2 = 1 - $percent2;

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

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

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

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

}

把distance2Verts()函數(shù)的定義加進(jìn)去,再把myEdgeChamfer()函數(shù)中的兩處splitByPercent()改為splitByDist(),這個(gè)程序就完成了。

附全部源代碼。

myEdgeChamfer_v2.rar (1.74k)

學(xué)習(xí) · 提示

  • 一定要打開(kāi)PS,跟著教程做一遍,做完的圖到這交作業(yè):提交作業(yè)
  • 建議練習(xí)時(shí),大家自己找素材,盡量不要用教程提供的素材。
  • 教程有看不懂的地方,可以到論壇發(fā)帖提問(wèn):新手求助
  • 加官方微信,隨時(shí)隨地,想學(xué)就能學(xué):ps_bbs,或掃右側(cè)二維碼!
  • 關(guān)注我們學(xué)更多,每天都有新教程:新浪微博 抖音視頻 微信小程序
- 發(fā)評(píng)論 | 交作業(yè) -
最新評(píng)論
暫無(wú)評(píng)論,交個(gè)作業(yè)支持一下吧~

關(guān)注大神微博加入>>

網(wǎng)友求助,請(qǐng)回答!