今回は選択エッジをエッジループ毎にグループ化する方法を紹介します。
例えば、下図左のように選択した場合、右のようにエッジループをグループ化します。
エッジからボーンチェインを作成したい場合など、エッジが連続したループになっている必要がある時に便利です。
残念ながらEdit_Polyモディファイアには対応していません。Editable_Poly専用です。
コード
-- 指定したEditable_Polyエッジをループ毎にグループ化する
-- Return: #(EdgeLoops, VertLoops)
fn getEdgeLoops polyMod edgeIds =
(
-- 引数edgeIdsをbitarrayに変換する
edgeIds = if isKindOf edgeIds bitarray then copy edgeIds
else edgeIds as bitarray
-- 頂点ごとのエッジID、エッジごとの頂点IDをリスト化する
local vertEdges = #()
local edgeVerts = #()
vertEdges.count = polyop.getNumVerts polyMod
edgeVerts.count = polyop.getNumEdges polyMod
for ei in edgeIds do
(
local v = polyop.getEdgeVerts polyMod ei
edgeVerts[ei] = v
local vEdges1 = vertEdges[v[1]]
local vEdges2 = vertEdges[v[2]]
if vEdges1 != undefined then append vEdges1 ei else vertEdges[v[1]] = #(ei)
if vEdges2 != undefined then append vEdges2 ei else vertEdges[v[2]] = #(ei)
)
-- 現在のエッジから次のエッジを検索する
fn _getNextEdge edges edgeIds =
(
local res = undefined
for ei in edges while res == undefined do
if edgeIds[ei] do res = ei
res
)
-- 現在の頂点から次の頂点を取得する
fn _getNextVert verts lastVert =
(
if verts[1] == lastVert then
verts[2]
else
verts[1]
)
-- エッジループを作成する
local edgeLoops = #()
local vertLoops = #()
for ei in edgeIds do
(
edgeIds[ei] = false -- Memo: ループ中にbitarrayの中身を変更すると、ループにも反映される
local vertLoop = copy edgeVerts[ei] #noMap
local edgeLoop = #(ei)
-- 正方向へ検索
local nextVert = vertLoop[2]
local nextEdge = _getNextEdge vertEdges[nextVert] edgeIds
while nextEdge != undefined do
(
nextVert = _getNextVert edgeVerts[nextEdge] nextVert
append vertLoop nextVert
append edgeLoop nextEdge
edgeIds[nextEdge] = false
nextEdge = _getNextEdge vertEdges[nextVert] edgeIds
)
-- 負方向へ検索
local nextVert = vertLoop[1]
local nextEdge = _getNextEdge vertEdges[nextVert] edgeIds
while nextEdge != undefined do
(
nextVert = _getNextVert edgeVerts[nextEdge] nextVert
insertItem nextVert vertLoop 1
insertItem nextEdge edgeLoop 1
edgeIds[nextEdge] = false
nextEdge = _getNextEdge vertEdges[nextVert] edgeIds
)
append edgeLoops edgeLoop
append vertLoops vertLoop
)
#(edgeLoops, vertLoops)
)
引数
- polyObj
- Editable_Polyベースオブジェクトまたはノード。
- edgeIds
- エッジIDを指定したbitarray。
戻り値
配列 #(edgeLoops, vertLoops)
- edgeLoop
- エッジID配列の配列。
- vertLoops
- 頂点ID配列の配列。
edgeLoopとvertLoopsは同じサイズになり、頂点数はエッジ数+1になる。
ここで、各配列の外側の配列が左図の#1, #2, #3のようにグループを格納し、内側の配列は右図のようなエッジIDと頂点IDの配列になります。
この時、必ずエッジIDと頂点IDは対応するループ順になるように取得されます。
また、以下のようにエッジが交差する場合は、パターンAのようになるかBのようになるかはその時のトポロジ構造により、エッジIDの若い順にルートを決定しているので、ほぼランダムとなります。詳細にコントロールしたい場合はコードを修正して、エッジ角によって選択するルートを変更するような仕組みにする必要があります。
もう一点、#3のようにエッジがリング状にループしている場合、基点として使用されるのは頂点IDの最も若い頂点となります。
その場合、取得した頂点の始点と終点は同じIDになるので、それを調べればエッジループが循環している事を知る事が出来ます。
21vvu8