Daz アニメーション
ダウンを喫し、なけなしの体力を振り絞ってなんとかロープ際まで這いずり、やっと掴んだロープを離してしまい目の前で虚しく揺れるロープを眺めることしかできない……の図です。
これは何?
Daz のアニメーション機能を試してみました。
Timeline ペインで時刻を動かしながら1フレームごとに動きをつけ、実行してみてアニメーションの動作確認……した時点でGUIでの反復移動がやってられなくなったので、本番ではスクリプトで動きを指定しました。スクリプト自体は末尾に。
作品としては人物のダメージ描写や表情が未設定とかロープが納まりきってないカメラアングルとか色々残念ですが、実験ということで。
でも、てかてかグローブにロープの影が映っているのはいいですね。
レンダリング時間
気になるレンダリング時間ですが、10fps10秒の100フレームで、100分ほどかかりました。普段Full HD画像一枚を撮るのと同じくらい。
480x270ピクセル、Max samples や Max path Length もかなり落として同等なので、気合入れた画質にしようとすると大変そうです。ライトやピンボケもとくに設定してません。動画は厳しい……。
今後の展望
スクリプトの書き方が分かったので、動かす先の座標さえ分かればちょっとした動きを付けるのは簡単にできそうです。
単純な式で表せる動きなら座標の計算も難しくないはず。ロープの振動のほか、みんな大好きマウスピースの放物線だとか、人物を前後上下させて自然な体の揺れを表現するとか。
夢はでっかくボクシングの動きをさせたいところですが、人体は連動して動くところが多いし単純な軌道でもなさそうなので、気合入れて手動で指定するしかなさそうな気がします……。
関節の連動の仕方をうまく模式化できればスクリプトでもいけるか……?
それはそうと、四元数と和解しなさい。
スクリプト
// DAZ Studio version 4.22.0.15 filetype DAZ Script
// 扱うボーンの取得
var blueRope = Scene.findNode("BoxingRingBody").findNodeChildByLabel("BlueCorner").findNodeChildByLabel("BlueRopeBottomL").findNodeChildByLabel("BlueRope")
var i, target_bone
const target_bone_id = 15
var temp_bone = blueRope.getNodeChild(0)
for (i = 1; i < target_bone_id; i++){
temp_bone = temp_bone.getNodeChild(0)
}
const target_bone = temp_bone
const reverse_bone = target_bone.getNodeChild(0)
for (temp_bone = reverse_bone; temp_bone.getNumNodeChildren() > 0; temp_bone = temp_bone.getNodeChild(0)){}
const end_bone = temp_bone
// ロープ揺れの各種パラメータ
const secondPerCycle = 2
const reductionFrames = 100
const fps = 10
const amplitude= -50
// 指定フレームごとのロープの位置
function rope_bound(frame){
const time = Scene.getTimeStep().valueOf() * frame
// ロープ頂点のy座標。振動しながら徐々に振幅が落ちるように
const y = amplitude * (reductionFrames - frame) / reductionFrames * Math.cos(2 * Math.PI * frame / fps / secondPerCycle)
// ロープ始点の曲げ角度。y座標に来るようロープの長さから計算する
const b_radian = Math.atan(y / (blueRope.getWSPos().x - target_bone.getWSPos().x))
// 反対側ロープの角度。同様に残りのロープの長さから計算する。
const e_radian = Math.atan(y / (end_bone.getWSPos().x - reverse_bone.getWSPos().x))
// ロープの各ボーンに動きを設定。四元数のことは何も分からん
// 第一引数は DzTime 型だが、DzTime のドキュメントには Number 入れていいって書いてある。ていうか DzTime にコンストラクタが用意されてない。
blueRope.setLocalRot(time, DzQuat(b_radian / Math.PI, 0, 0, 1))
target_bone.setLocalRot(time, DzQuat(-1 * b_radian / Math.PI, 0, 0, 1))
reverse_bone.setLocalRot(time, DzQuat(e_radian / Math.PI, 0, 0, 1))
}
// 全フレームにそれぞれの時刻での動きを設定
for (i = 0; i <= reductionFrames; i++){
rope_bound(i)
}