_581x100.png CGsyomei_583x102.gif 訪問者 無料カウンター ページビュー 無料カウンター

2011年07月25日

選択したポリゴン面の一括デタッチとその注意事項

detach_result.jpg

編集可能ポリゴンの選択したポリゴン面を全て一括でデタッチして別オブジェクトにしようと思い色々調べたところ次のようなスクリプトを見つけました。

poly_count = polyop.getNumFaces $

for i = poly_count to 1 by -1 do

(
   polyOp.detachFaces $ #{i} asNode:true name:"Object01"

)

使い方は、編集可能ポリゴンにしたオブジェクトのポリゴン面を選択し、スクリプトを実行するだけです。各ポリゴンはObject01と名前のついたそれぞれ別オブジェクトになります。


スクリプトのヘルプによれば、polyop.getNumFaces $は選択したポリゴン面の数を返し、 polyop.detachFaces $は選択しているポリゴン面をそれぞれデタッチします。後ろについているasNode:trueはデタッチした後に別ノード、つまり別オブジェクトにするかということで、name:"explodedObject"は別オブジェクトにしたものに名前をつけるためのオプションです。

 このスクリプトを見ててどうも腑に落ちないところがあったのですが、それはなぜfor i = poly_count to 1 by -1 do と、トータルのポリゴン面数から1へと数字を繰り下げながらfor loopを回しているのかということです。ちなみにこのように

poly_count = polyop.getNumFaces $

for i = 1 to poly_count do

(
polyOp.detachFaces $ #{i} asNode:true name:"Object01"

)

1から順に処理していく方法だと以下のようなエラーが出てfor loopの4回目以降が走りません。

-- Frame:
-- i: 4
-- Runtime error: EPoly face index out of range: < 1 or > 3: 4


これに関してツイッターで質問をしたところ、@k240さんと@daiiiさんに非常に分かりやすく説明して頂きました。

 ポリゴン面には1から順番にインデックス番号が割り振られています。それがデタッチする順番が前からだと、1を消すと、2だったものが1になりますが、後ろからだと、インデックスと面の関係が変わらないので

for i = poly_count to 1 by -1 do

この場合はfor loopが回ります、、、とのことです^^;

 ちなみにpoly_count to 1 by -1 do がどういう処理をしているのかシンプルなボックスのように6枚のポリゴン面を持つオブジェクトで考えてみます。polyOp.detachFaces $ #{i} asNode:true name:"Object01"の部分もprint iに置き換えて#{i}のiに入っていく配列の数がどうなっていくのかを確認します。

poly_count = polyop.getNumFaces $

for i = poly_count to 1 by -1 do
(
print i
)

これを走らせると、リスナーには

6
6
5
4
3
2
1
OK

と帰ってきます。最初の6は変数poly_countに入るポリゴン面の数の6。以下6から1に向かってー1ごと、つまり逆に下っていくということです。この順番でポリゴンをデタッチしていくとエラーが起きないということです。


頭で考えても分かりづらいので実際に簡単なモデルを作って検証してみました。以下のような板が並んでいるけど一つのオブジェクトがあるとします。上の数字は各面のインデックス番号です。↓

model_base.jpg

6番目のインデックスの面をデタッチしてハイドしたとすると次はこうなります。↓

detach_6.jpg

もともとある1から5のインデックスが振られたポリゴン面の関係は崩れません。あとは図を示すまでもなく最後まで同じような処理がされていきます。

ではfor i = 1 to poly_count do の場合はどうでしょうか。for loop内ではインデックス番号1、2、3、、、、と処理されていきます。ではまず最初の状態からです。↓

model_base.jpg

インデックス番号1のポリゴン面をデタッチします。イメージはこう。↓

detach_1.jpg

で、次にオブジェクト内でどういうことが起こるかというと、ポリゴン面のインデックス番号がまた1から割り振られ直されるんですね。なのでこうなります。↓

sort_sfter_detach_1.jpg

では次に起こる処理は何かというと、インデックス番号2のポリゴン面がデタッチされます。イメージはこう。↓

detach_2.jpg

で、またインデックス番号が割り振られ直されます。↓

sort_sfter_detach_2.jpg

この状態から次はインデックス番号3のポリゴン面をデタッチします。イメージは以下の通り。↓

detach_3.jpg

で、同じように再度インデックス番号が割り振られます。↓

sort_sfter_detach_3.jpg

さて次はエラーが出た問題のfor loop4回目です。でももう見ての通り、インデックス番号4が割り振られたポリゴン面は存在しないんですね。なので4番のポリゴンなんてないぞということでエラーが帰ってきてスクリプトが走らないということです。このデタッチされるたびにインデックス番号が再度割り振られるという約束事を知らなければなぜエラーが起きるのか分かりづらいと思います。

さらに@daiiiさんが

poly_count = polyop.getNumFaces $

for i = 1 to poly_count do

(
polyOp.detachFaces $ #{1} asNode:true name:"Object01"

)

これもOKと言っていて、これも最初はぴんときませんでした。エラーを起こしていたスクリプトだと#{i}なのが#{1}と数字の1になっただけなんですが、これも中の処理を見てみたら、常に最初の1のインデックスを消していくという意味なんですね。なので以下のようになります。

まずは最初の状態。↓

model_base.jpg

次に1のインデックス番号のポリゴン面をデタッチ。↓

detach_1.jpg


次に番号が再度割り振られます。↓

sort_sfter_detach_1.jpg

次も1のインデックス番号のポリゴン面をデタッチ。↓

1to5_detach_1.jpg

そしてインデックス番号の割り振り直し。↓

sort1234.jpg

であとはデタッチの繰り返し番号の割り振りの繰り返しとということになります。今後こういうインデックス番号が変わることで起こるエラーに出くわしたときにこういうのを頭に入れておくとスムーズに対処できると思います。いやー、ほんと勉強になりました。





posted by けゑ at 07:51| Comment(2) | TrackBack(0) | Max Script
この記事へのコメント
インデックスの再振り分けを行うのなら大量のインデックスの場合、再振り分け処理に時間がかかるので、減算を基本に処理を構築するのがセオリーと考えておくほうがいいかもしれませんね。この再振り分けが、どのCGソフトでも同じように処理するのかはまた別途気になりますね。勉強になります!
Posted by gameeffect at 2011年08月01日 21:48
>gameeffectさん こういうセオリーがあるっていうのはほんと目から鱗でした。まだまだスクリプトは手数が足りていないのでもっと色々試してみて誰しもがはまる部分をどんどんクリアにしていきたいです。
Posted by けゑ at 2011年09月01日 05:52
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

この記事へのトラックバックURL
http://blog.sakura.ne.jp/tb/46940244

この記事へのトラックバック