myara CG blog

CG Design Blog. Thoughts, experiments and experiences.

Select Mirror Components ver.2

前回、Select Mirror Components というスクリプトをアップしましたが、仕事で試してみたらちょっとした問題が出てしまいました。

キャラクターの左手だけをいじっていて、右側に持って行きたい時にミラー選択して消せば良いと思ったけど、このスクリプトは完全に左右対称じゃないと何も選択してくれません。

mSelectMirrorComp2-1.gif

EqualRange 範囲の変数を変えると微妙にずれているコンポーネントも選択されるようになるので、ダイアログウィンドウでこの変数をスライダーで変更できるようにしました。

でも、ポリゴン数とか割り方が違ったらやっぱり選択されません。

なので、もう一つの選び方を入れてみました。

レクタングル選択です。
要するに、選択されたコンポーネントのXYZ軸の最小値から最大値までに入っているコンポーネントを選択します。

mSelectMirrorComp2-2.gif

レクタングル選択のような機能なので、こんなこともありうるので注意して下さい:

mSelectMirrorComp2-3.gif

スクリプトは同じリンクです:DOWNLOAD

CTRL = ダイアログメニュー
ALT = レクタングル選択
SHIFT = 両サイド選択

CTRL + SHIFT とかも可能です。

エッジとポリゴンのレクタングル選択は真中の位置で計算されます。

mSelectMirrorComp2-4.gif

-----

ここからまたスクリプティング的な話です。

今回はエッジ選択が30~40%速くなりました。

前回言っていた「XYZ位置を比べる時に、XYZ同時より、軸を一つずつ絞っていったほうが速いです。」今回をこのラインで似たようなことをやってみました:
if oStart.EpsilonEquals(oEStart, range) and oEnd.EpsilonEquals(oEEnd, range) then
selEdges.Addelement oEdge.Index
Exit for
End if


変数名とかforループも入れてないから、これを見ても分からない人も居ると思うので簡単に説明します。

選択したエッジのスタート位置(oStart)とエンド位置(oEnd)をEpsilonEqualsで全エッジのスタート位置とエンド位置と比べて、位置の差はrange以下場合、そのエッジをコレクションに入れて、Forループを終了。
というコードです。

これを2回で分けてみました。まずはスタート位置だけ比べて、これをクリアすればエンド位置を比べてからコレクションに追加します。

1回目の条件で落ちたら2回目の比較を実行せずに次のエッジの計算を始めて、ダメなエッジはエプシロンなんちゃらは1回だけで済むから速いです。

if oStart.EpsilonEquals(oEStart, range) then
if oEnd.EpsilonEquals(oEEnd, range) then
selEdges.Addelement oEdge.Index
Exit for
end if
End if



こういうコードをこんな風に直したらエッジ選択スクリプトが30~50%上がりました。

そして、もう一つ。

これはエッジのレクタングル選択を書いてた時:

dim oEdgeposx, oEdgeposy, oEdgeposz
oEdgeposx = (oEdgeStartPos.x + oEdgeEndPos.x) /2
oEdgeposy = (oEdgeStartPos.y + oEdgeEndPos.y) /2
oEdgeposz = (oEdgeStartPos.z + oEdgeEndPos.z) /2
if oEdgeposx - range < Maxposx and oEdgeposx + range > Minposx then
if oEdgeposy - range < Maxposy and oEdgeposy + range > Minposy then
if oEdgeposz - range < Maxposz and oEdgeposz + range > Minposz then
selEdges.Addelement oEdge.Index
end if
end if
end if


あらかじめエッジの真中位置を計算してから、比べ始めてXYZ軸を3段階に分けてあるコードです。

これはXYZ軸を同時に比べるより速いです。実験では 2400ミリ秒 から 2300ミリ秒 になりました。

が、さらに速く出来ます。

ここはエッジの真中位置を計算しておくのではなく、比べるときに計算するように変更しました;

dim oEdgePosx, oEdgePosy, oEdgePosz
oEdgePosx = (oEdgeStartPos.x + oEdgeEndPos.x) /2
if oEdgePosx - range < MaxPosx and oEdgePosx + range > MinPosx then
oEdgePosy = (oEdgeStartPos.y + oEdgeEndPos.y) /2
if oEdgePosy - range < MaxPosy and oEdgePosy + range > MinPosy then
oEdgePosz = (oEdgeStartPos.z + oEdgeEndPos.z) /2
if oEdgePosz - range < MaxPosz and oEdgePosz + range > MinPosz then
selEdges.Addelement oEdge.Index
end if
end if
end if


実験の結果は 2300ミリ秒 から 2000ミリ秒 になりました。

以上。
Previous page Next page