ON-BLOG

CGのこと、あれこれ書いてます。

のび留

「ストレッチボーン」

いつかやってみたい。

そんな妄想を日々思ってました。

といっても、ちょこちょこ触ってましたが。。。

 

 

で、例の如くwebを徘徊してるとこんな記事見つけました。

http://www.christoph-schinko.com/tutorials/schinko_arm_en.pdf

※巨大PDFです。。

 

ストレッチボーンに関しての記事みたいです。

よくよく見ると、結構面白そうだったので、今回はこれを日本語化を含め記事にしてみます。

 

使用言語はもちろんJscriptです。

ではまず。

コードがこれ。

https://github.com/tommyon/tommy_local/blob/master/stretch_Bone.js

色々と抜いてますw

f:id:tommy_on:20130613011602j:plain

f:id:tommy_on:20130613011641j:plain

コード自体はOn/Off付けた時点で終了してます。

実行方法はヌルを2個以上配置ください。

あとは実行するだけでOKです。

第一ボーンにカスタムプロパティを仕込んでます。

※ボーンにカスタムプロパティを仕込むのはあんまりよくないかも。。

これをOn/Offで切り替える事でストレッチの切り替えができます。

f:id:tommy_on:20130613011829j:plain

f:id:tommy_on:20130613011905j:plain

というスクリプトです。

 

これの元ネタになったのが、上記リンクです。

ではリンク先に書かれている内容を超簡単に和訳してみます。

 

 

I. STRETCH

1. Create a 2-bone chain in the right viewport and name the root “r_arm”, the bones “b_upArm” and

“b_loArm”, and the effector “e_arm”. This naming convention makes it easy to follow this tutorial and

allows for quick selection from XSIs’ MCP, using “b_*” etc.

 

ライトビューで骨2つ作成

名前をルートを「r_arm」

エフェクタ「e_arm」

第一骨を「b_b_upArm」

第二骨を「b_loArm」とする。

 

3. create a null (name it “dist”) to measure and at the same time display the distance between the eff

and root.

4. Set an expression on the local y translation of the null (kine.local.posy), enter the following

expression 

ctr_dist( r_arm.kine.global.pos, e_arm.kine.global.pos )

and hitapply.

 

ヌルを作成し名前を「dist」

を変更。

「dist.kine.local.posy」に対して以下の式記載

ctr_dist( r_arm.kine.global.pos, e_arm.kine.global.pos )

これでルートとエフェクタの距離がposYで表されます。

この時点でdistのポジションYは二点の距離を表してます。

別に「ctr_dist」じゃなくても三角関数使えば距離は取れますが、便利なんで。

 

 

5. Apply an expression on the length of the upper arm, telling it that when the distance from the

effector to the chain root is bigger than the sum of both original bone lengths (hence, a stretched arm),

7) will be referred to as straight arm distance.

Cond(dist.kine.local.posy > 7, 3 + (dist.kine.local.posy - 7) /2, 3)

6. Apply the same expression to the lower arm, taking into account that its original length was 4, not 3

Cond(dist.kine.local.posy > 7, 4 + (dist.kine.local.posy - 7) /2, 4)

 

で、次に骨を選択しそれぞれ、第一骨「3」第二骨「4」

と入力。

第一骨の長さに以下の式を挿入

「Cond(dist.kine.local.posy > 7, 3 + (dist.kine.local.posy - 7) / 2, 3)」

第二骨にいは、↓

「Cond(dist.kine.local.posy > 7, 4 + (dist.kine.local.posy - 7) / 2, 4)」

これで骨にストレッチ効果が現れます。

 

では上記文の説明を

「Cond」は条件文です。

ifと同じを考えてもらって問題ありません。

Cond分は第一引数に「条件文」第二引数に「True時の処理」第三引数に「False時の処理」

を記載しています。

で、それらを踏まえ、まずは条件文ですが、

「dist.kine.local.posy > 7」これはヌル「dist」のポジションYが

7より低かったら。という意味になります。

で「,」で区切った第二引数では、

■True時の処理

「3 + (dist.kine.local.posy - 7) / 2」

という式が実行されます。

中身を見ますと、

「3 + (distのポジションY - 7) /2」となります。

置き換えると

「骨の標準の長さ」+(「現時点のルート、エフェクタの距離」- 「標準時のルート、エフェクタの距離」)/骨の数」

となります。

こう見ると分かりやすいかもです。

って事で要は

骨の長さと2点の距離を出してるわけです。

で第三引数

■False時の処理

「3」となっております。

これは条件式で弾かれた時の値ですね。

デフォルトの骨の長さです。

 

 

II. RESET AND LOCK

As it might be better to block in any animation with a “locked”, fixed-length chain and only animate

over-stretching later on, the ability to disable the chains stretchiness is important. 

Also, when posing a character, it will be nice to be able to reset any accidental over-stretching, making

the arm snap back to its original length without losing the pose (along the eff/root-axis).

A condition in the length expressions can take care of that, only allowing a change of bone lengths

when a new reset-and-lock parameter is 0. As the bone lengths both rely on the measured distance, it’s

easiest to go in there to control the bones’ behaviour.

7. Create another null (“resetAndLock”), then

8. change the expression of the “dist”-null to the following

cond( resetAndLock.kine.local.posy == 0, ctr_dist(

r_arm.kine.global.pos, e_arm.kine.global.pos ), 7 )

 

 

こんな感じストレッチ骨が仕込めます。

で次にこのままだと常にストレッチがOnになってます。

これを制御できるようにします。

やり方は簡単です。

まずは制御用のヌルを作成し、名前を

「resetAndLock」

として下さい。

先ほど仕込んだdistのエクスプレッションを開き、下記に書き換えます。

cond( resetAndLock.kine.local.posy == 0, 

ctr_dist(r_arm.kine.global.pos, e_arm.kine.global.pos ), 7 )

これで完成です。

説明しますと、

先ほど作成した、「resetAndLock」がポジションYが0の時だけストレッチが効く。

という式を追加しました。

内容は非常に簡単なんで、飛ばします。

 

 

III. STRETCH OFFSET

10. Edit the expression on upArm.bone.length.

before:

cond( dist.kine.local.posy > 7, 3 +

( dist.kine.local.posy - 7 ) / 2, 3 )

after:

cond( dist.kine.local.posy > 7, 3 +

( dist.kine.local.posy - 7 ) / 2, 3 ) +

stretch.kine.local.sclx + stretchUp.kine.local.sclx - 2

The “-2” is to compensate for the control objects’ initial scaling values (of 1 each), so a scaling of “1”

means no offset (0).

11. Do the same for the loArm.bone.length (remember that it’s original length was different)

cond( dist.kine.local.posy > 7, 4 + ( dist.kine.local.posy -

7 ) / 2, 4 ) + stretch.kine.local.sclx +

stretchLo.kine.local.sclx - 2

 

 

このままでスケールを掛けると、ストレッチが破たんします。

それを回避するため、骨の長さに仕込んでいたエクスプレッションに編集を加えます。

加える前に以下名前のヌルを作成してください。

「stretchUp」「stretch」「stretchLo」

場所はどこでもいいですが、スケール値は「1」固定で。

そして以下の式を変更してください。

第一ボーン

「長さ」

編集前

cond( dist.kine.local.posy > 7, 3 +( dist.kine.local.posy - 7 ) / 2, 3 )

編集後

cond( dist.kine.local.posy > 7, 3 +( dist.kine.local.posy - 7 ) / 2, 3 )

+stretch.kine.local.sclx + stretchUp.kine.local.sclx - 2

第二ボーン

編集前

cond( dist.kine.local.posy > 7, 4 + ( dist.kine.local.posy -7 ) / 2, 4 )

編集後

cond( dist.kine.local.posy > 7, 4 + ( dist.kine.local.posy -7 ) / 2, 4 )

+ stretch.kine.local.sclx +stretchLo.kine.local.sclx - 2

 

はい。

とりあえずここで切ります。

あとはそんなに気になる点なかったんですよ。。

けどここまでの段階で、なんとなくストレッチボーンは仕込めてます。

RIGで組む場合は「LR」の仕切りは必要です。

 

とまぁ色々と世の中には親切な方がいるものです。

 

では…